Esempio n. 1
0
extern "C" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpCmdLine*/, int /*nShowCmd*/)
{
#ifdef CRASH_HANDLER
    rde::CrashHandler::Init();
#endif

	// disable auto-rotate on tablets
#if (WINVER <= 0x0601)
    SetDisplayAutoRotationPreferences = (pSDARP) GetProcAddress(GetModuleHandle(TEXT("user32.dll")),
                                                                "SetDisplayAutoRotationPreferences");
    if(SetDisplayAutoRotationPreferences)
        SetDisplayAutoRotationPreferences(ORIENTATION_PREFERENCE_LANDSCAPE);
#else
    SetDisplayAutoRotationPreferences(ORIENTATION_PREFERENCE_LANDSCAPE);
#endif

	g_hinst = hInstance;
   
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
    HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
#else
    HRESULT hRes = CoInitialize(NULL);
#endif
    _ASSERTE(SUCCEEDED(hRes));
    _Module.Init(ObjectMap, hInstance, &LIBID_VPinballLib);

	bool fFile = false;
	bool fPlay = false;
    bool bRun = true;
	TCHAR szTableFileName[_MAX_PATH] = {0};
    int nRet = 0;

    int nArgs;
	LPSTR *szArglist = CommandLineToArgvA(GetCommandLine(), &nArgs);

	for(int i=0; i < nArgs; ++i)
    {
        if (lstrcmpi(szArglist[i], _T("-UnregServer"))==0 || lstrcmpi(szArglist[i], _T("/UnregServer"))==0)
        {
            _Module.UpdateRegistryFromResource(IDR_VPINBALL, FALSE);
            nRet = _Module.UnregisterServer(TRUE);
            bRun = false;
			break;
        }
        if (lstrcmpi(szArglist[i], _T("-RegServer"))==0 || lstrcmpi(szArglist[i], _T("/RegServer"))==0)
        {
            _Module.UpdateRegistryFromResource(IDR_VPINBALL, TRUE);
            nRet = _Module.RegisterServer(TRUE);
            bRun = false;
			break;
        }

		const bool editfile = (lstrcmpi(szArglist[i], _T("-Edit"))==0 || lstrcmpi(szArglist[i], _T("/Edit"))==0);
		const bool playfile = (lstrcmpi(szArglist[i], _T("-Play"))==0 || lstrcmpi(szArglist[i], _T("/Play"))==0);
        if ((editfile || playfile) && (i+1 < nArgs))
        {
			fFile = true;
			fPlay = playfile;

			// Remove leading - or /
			char* filename;
			if((szArglist[i+1][0] == '-') || (szArglist[i+1][0] == '/'))
				filename = szArglist[i+1]+1;
			else
				filename = szArglist[i+1];

			// Remove " "
			if(filename[0] == '"') {
				strcpy_s(szTableFileName,filename+1);
				szTableFileName[lstrlen(szTableFileName)] = '\0';
			}
			else
				strcpy_s(szTableFileName,filename);

			// Add current path
			char szLoadDir[MAX_PATH];
			if(szTableFileName[1] != ':') {
				GetCurrentDirectory(MAX_PATH,szLoadDir);
				strcat_s(szLoadDir,"\\");
				strcat_s(szLoadDir,szTableFileName);
				strcpy_s(szTableFileName,szLoadDir);
			} else
				// Or set from table path
				if(playfile) {
					PathFromFilename(szTableFileName, szLoadDir);
					SetCurrentDirectory(szLoadDir);
				}

			if(playfile)
				VPinball::SetOpenMinimized();

			break;
        }
    }

	free(szArglist);

    // load and register VP type library for COM integration
    char szFileName[_MAX_PATH];
    if (GetModuleFileName(hInstance, szFileName, _MAX_PATH))
    {
        ITypeLib *ptl = NULL;
        MAKE_WIDEPTR_FROMANSI(wszFileName, szFileName);
        if (SUCCEEDED(LoadTypeLib(wszFileName, &ptl)))
        {
            // first try to register system-wide (if running as admin)
            HRESULT hr = RegisterTypeLib(ptl, wszFileName, NULL);
            if (!SUCCEEDED(hr))
            {
                // if failed, register only for current user
                hr = RegisterTypeLibForUser(ptl, wszFileName, NULL);
                if (!SUCCEEDED(hr))
                    MessageBox(0, "Could not register type library. Try running Visual Pinball as administrator.", "Error", MB_ICONWARNING);
            }
            ptl->Release();
        }
        else
            MessageBox(0, "Could not load type library.", "Error", MB_ICONSTOP);
    }

    if (bRun)
    {
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
        hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER,
            REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED);
        _ASSERTE(SUCCEEDED(hRes));
        hRes = CoResumeClassObjects();
#else
        hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER,
            REGCLS_MULTIPLEUSE);
#endif
        _ASSERTE(SUCCEEDED(hRes));

		INITCOMMONCONTROLSEX iccex;
		iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
		iccex.dwICC = ICC_COOL_CLASSES;
		InitCommonControlsEx(&iccex);

        {
            EditableRegistry::RegisterEditable<Bumper>();
            EditableRegistry::RegisterEditable<Decal>();
            EditableRegistry::RegisterEditable<DispReel>();
            EditableRegistry::RegisterEditable<Flasher>();
            EditableRegistry::RegisterEditable<Flipper>();
            EditableRegistry::RegisterEditable<Gate>();
            EditableRegistry::RegisterEditable<Kicker>();
            EditableRegistry::RegisterEditable<Light>();
            EditableRegistry::RegisterEditable<LightSeq>();
            EditableRegistry::RegisterEditable<Plunger>();
            EditableRegistry::RegisterEditable<Primitive>();
            EditableRegistry::RegisterEditable<Ramp>();
            EditableRegistry::RegisterEditable<Rubber>();
            EditableRegistry::RegisterEditable<Spinner>();
            EditableRegistry::RegisterEditable<Surface>();
            EditableRegistry::RegisterEditable<Textbox>();
            EditableRegistry::RegisterEditable<Timer>();
            EditableRegistry::RegisterEditable<Trigger>();
        }

		g_pvp = new VPinball();
		g_pvp->AddRef();
		g_pvp->Init();
		g_haccel = LoadAccelerators(g_hinst,MAKEINTRESOURCE(IDR_VPACCEL));

		if (fFile)
			{
			g_pvp->LoadFileName(szTableFileName);

			if (fPlay)
				g_pvp->DoPlay();
			}

		// VBA APC handles message loop (bastards)
		g_pvp->MainMsgLoop();

		g_pvp->Release();

		DestroyAcceleratorTable(g_haccel);

        _Module.RevokeClassObjects();
        Sleep(dwPause); //wait for any threads to finish
    }

    _Module.Term();
    CoUninitialize();
#ifdef _CRTDBG_MAP_ALLOC
#ifdef DEBUG_XXX  //disable this in perference to DevPartner
	_CrtSetDumpClient(MemLeakAlert);
#endif
	_CrtDumpMemoryLeaks();
#endif
	//SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF );

    return nRet;
}
Esempio n. 2
0
// (Un)Register the ActiveX server in the registry.
// The QAxFactory implementation provides the information.
HRESULT UpdateRegistry(BOOL bRegister)
{
    qAxIsServer = false;
    const QChar dot(QLatin1Char('.'));
    const QChar slash(QLatin1Char('/'));
    QString file = QString::fromWCharArray(qAxModuleFilename);
    const QString module = QFileInfo(file).baseName();

    const QString appId = qAxFactory()->appID().toString().toUpper();
    const QString libId = qAxFactory()->typeLibID().toString().toUpper();

    const QString libFile = qAxInit();

    TLIBATTR *libAttr = 0;
    if (qAxTypeLibrary)
        qAxTypeLibrary->GetLibAttr(&libAttr);
    if (!libAttr)
        return SELFREG_E_TYPELIB;
    bool userFallback = false;
    if (bRegister) {
        if (RegisterTypeLib(qAxTypeLibrary,
                            reinterpret_cast<wchar_t *>(const_cast<ushort *>(libFile.utf16())), 0) == TYPE_E_REGISTRYACCESS) {
#ifndef Q_CC_MINGW
            // MinGW does not have RegisterTypeLibForUser() implemented so we cannot fallback in this case
            RegisterTypeLibForUser(qAxTypeLibrary, reinterpret_cast<wchar_t *>(const_cast<ushort *>(libFile.utf16())), 0);
            userFallback = true;
#endif
        }
    } else {
        if (UnRegisterTypeLib(libAttr->guid, libAttr->wMajorVerNum, libAttr->wMinorVerNum, libAttr->lcid,
                              libAttr->syskind) == TYPE_E_REGISTRYACCESS) {
#ifndef Q_CC_MINGW
            // MinGW does not have RegisterTypeLibForUser() implemented so we cannot fallback in this case
            UnRegisterTypeLibForUser(libAttr->guid, libAttr->wMajorVerNum, libAttr->wMinorVerNum, libAttr->lcid, libAttr->syskind);
            userFallback = true;
#endif
        }
    }
    if (userFallback)
        qWarning("QAxServer: Falling back to registering as user for %s due to insufficient permission.", qPrintable(module));
    qAxTypeLibrary->ReleaseTLibAttr(libAttr);

    // check whether the user has permission to write to HKLM\Software\Classes
    // if not, use HKCU\Software\Classes
    QString keyPath(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes"));
    QScopedPointer<QSettings> settings(new QSettings(keyPath, QSettings::NativeFormat));
    if (userFallback || !settings->isWritable()) {
        keyPath = QLatin1String("HKEY_CURRENT_USER\\Software\\Classes");
        settings.reset(new QSettings(keyPath, QSettings::NativeFormat));
    }

    // we try to create the ActiveX widgets later on...
    bool delete_qApp = false;
    if (!qApp) {
        static int argc = 0; // static lifetime, since it's passed as reference to QApplication, which has a lifetime exceeding the stack frame
        (void)new QApplication(argc, 0);
        delete_qApp = true;
    }

    if (bRegister) {
        if (qAxOutProcServer) {
            settings->setValue(QLatin1String("/AppID/") + appId + QLatin1String("/."), module);
            settings->setValue(QLatin1String("/AppID/") + module + QLatin1String(".EXE/AppID"), appId);
        }

        const QStringList keys = qAxFactory()->featureList();
        for (const QString &classNameIn : keys) {
            QObject *object = qAxFactory()->createObject(classNameIn);
            const QMetaObject *mo = qAxFactory()->metaObject(classNameIn);
            const QString classId = qAxFactory()->classID(classNameIn).toString().toUpper();

            const QString className = qax_clean_type(classNameIn, mo);

            if (object) { // don't register subobject classes
                QString classVersion = mo ? QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("Version")).value()) : QString();
                if (classVersion.isNull())
                    classVersion = QLatin1String("1.0");
                bool insertable = mo && !qstricmp(mo->classInfo(mo->indexOfClassInfo("Insertable")).value(), "yes");
                bool control = object->isWidgetType();
                QString classMajorVersion = classVersion.left(classVersion.indexOf(dot));
                uint olemisc = OLEMISC_SETCLIENTSITEFIRST
                    |OLEMISC_ACTIVATEWHENVISIBLE
                    |OLEMISC_INSIDEOUT
                    |OLEMISC_CANTLINKINSIDE
                    |OLEMISC_RECOMPOSEONRESIZE;
                if (!control)
                    olemisc |= OLEMISC_INVISIBLEATRUNTIME;
                else if (object->findChild<QMenuBar*>() && !qax_disable_inplaceframe)
                    olemisc |= OLEMISC_WANTSTOMENUMERGE;

                const QString versionLessProgId = module + dot + className;
                const QString progId = versionLessProgId + dot + classMajorVersion;
                QString key = slash + progId;
                settings->setValue(key + QLatin1String("/."), className + QLatin1String(" Class"));
                settings->setValue(key + QLatin1String("/CLSID/."), classId);
                if (insertable)
                    settings->setValue(key + QLatin1String("/Insertable/."), QVariant(QLatin1String("")));

                key = slash + module + dot + className;
                settings->setValue(key + QLatin1String("/."), className + QLatin1String(" Class"));
                settings->setValue(key + QLatin1String("/CLSID/."), classId);
                settings->setValue(key + QLatin1String("/CurVer/."), progId);

                key = QLatin1String("/CLSID/") + classId;
                settings->setValue(key + QLatin1String("/."), className + QLatin1String(" Class"));
                if (file.endsWith(QLatin1String("exe"), Qt::CaseInsensitive))
                    settings->setValue(key + QLatin1String("/AppID"), appId);
                if (control)
                    settings->setValue(key + QLatin1String("/Control/."), QVariant(QLatin1String("")));
                if (insertable)
                    settings->setValue(key + QLatin1String("/Insertable/."), QVariant(QLatin1String("")));
                if (file.endsWith(QLatin1String("dll"), Qt::CaseInsensitive))
                    settings->setValue(key + QLatin1String("/InProcServer32/."), file);
                else
                    settings->setValue(key + QLatin1String("/LocalServer32/."),
                                      QLatin1Char('\"') + file + QLatin1String("\" -activex"));
                settings->setValue(key + QLatin1String("/MiscStatus/."), control ? QLatin1String("1") : QLatin1String("0"));
                settings->setValue(key + QLatin1String("/MiscStatus/1/."), QString::number(olemisc));
                settings->setValue(key + QLatin1String("/Programmable/."), QVariant(QLatin1String("")));
                settings->setValue(key + QLatin1String("/ToolboxBitmap32/."), QLatin1Char('\"') +
                                  file + QLatin1String("\", 101"));
                settings->setValue(key + QLatin1String("/TypeLib/."), libId);
                settings->setValue(key + QLatin1String("/Version/."), classVersion);
                settings->setValue(key + QLatin1String("/VersionIndependentProgID/."), versionLessProgId);
                settings->setValue(key + QLatin1String("/ProgID/."), progId);

                QString mime = QLatin1String(mo->classInfo(mo->indexOfClassInfo("MIME")).value());
                if (!mime.isEmpty()) {
                    QStringList mimeTypes = mime.split(QLatin1Char(';'));
                    for (int m = 0; m < mimeTypes.count(); ++m) {
                        mime = mimeTypes.at(m);
                        if (mime.isEmpty())
                            continue;
                        QString extension;
                        while (mime.contains(QLatin1Char(':'))) {
                            extension = mime.mid(mime.lastIndexOf(QLatin1Char(':')) + 1);
                            mime.chop(extension.length() + 1);
                            // Prepend '.' before extension, if required.
                            extension = extension.trimmed();
                            if (!extension.startsWith(dot))
                                extension.prepend(dot);
                        }

                        if (!extension.isEmpty()) {
                            key = slash + extension;
                            settings->setValue(key + QLatin1String("/."), module + dot + className);
                            settings->setValue(key + QLatin1String("/Content Type"), mime);

                            mime.replace(slash, QLatin1Char('\\'));
                            key = QLatin1String("/MIME/Database/Content Type/") + mime;
                            settings->setValue(key + QLatin1String("/CLSID"), classId);
                            settings->setValue(key + QLatin1String("/Extension"), extension);
                        }
                    }
                }

                delete object;
                qCDebug(lcAxRegistration).nospace().noquote() << "Registered \"" << progId
                    << "\"/" << classId << ", \"" << file << "\" at \"" << keyPath
                    << "\", insertable=" << insertable << ", control=" << control
                    << ", olemisc=" << hex << showbase << olemisc
                    << ", mime=" << mime;
            }

            qAxFactory()->registerClass(classNameIn, settings.data());
        }
    } else {
        if (qAxOutProcServer) {
            settings->remove(QLatin1String("/AppID/") + appId + QLatin1String("/."));
            settings->remove(QLatin1String("/AppID/") + module + QLatin1String(".EXE"));
        }
        const QStringList keys = qAxFactory()->featureList();
        for (const QString &classNameIn : keys) {
            const QMetaObject *mo = qAxFactory()->metaObject(classNameIn);
            const QString classId = qAxFactory()->classID(classNameIn).toString().toUpper();
            const QString className = qax_clean_type(classNameIn, mo);

            QString classVersion = mo ? QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("Version")).value()) : QString();
            if (classVersion.isNull())
                classVersion = QLatin1String("1.0");
            const QString classMajorVersion = classVersion.left(classVersion.indexOf(dot));

            qAxFactory()->unregisterClass(classNameIn, settings.data());
            const QString progId = module + dot + className + dot + classMajorVersion;
            QString key = slash + progId;
            settings->remove(key + QLatin1String("/CLSID/."));
            settings->remove(key + QLatin1String("/Insertable/."));
            settings->remove(key + QLatin1String("/."));
            settings->remove(key);

            key = slash + module + dot + className;
            settings->remove(key + QLatin1String("/CLSID/."));
            settings->remove(key + QLatin1String("/CurVer/."));
            settings->remove(key + QLatin1String("/."));
            settings->remove(key);

            key = QLatin1String("/CLSID/") + classId;
            settings->remove(key + QLatin1String("/AppID"));
            settings->remove(key + QLatin1String("/Control/."));
            settings->remove(key + QLatin1String("/Insertable/."));
            settings->remove(key + QLatin1String("/InProcServer32/."));
            settings->remove(key + QLatin1String("/LocalServer32/."));
            settings->remove(key + QLatin1String("/MiscStatus/1/."));
            settings->remove(key + QLatin1String("/MiscStatus/."));
            settings->remove(key + QLatin1String("/Programmable/."));
            settings->remove(key + QLatin1String("/ToolboxBitmap32/."));
            settings->remove(key + QLatin1String("/TypeLib/."));
            settings->remove(key + QLatin1String("/Version/."));
            settings->remove(key + QLatin1String("/VersionIndependentProgID/."));
            settings->remove(key + QLatin1String("/ProgID/."));
            settings->remove(key + QLatin1String("/."));
            settings->remove(key);

            QString mime = QLatin1String(mo->classInfo(mo->indexOfClassInfo("MIME")).value());
            if (!mime.isEmpty()) {
                QStringList mimeTypes = mime.split(QLatin1Char(';'));
                for (int m = 0; m < mimeTypes.count(); ++m) {
                    mime = mimeTypes.at(m);
                    if (mime.isEmpty())
                        continue;
                    QString extension;
                    while (mime.contains(QLatin1Char(':'))) {
                        extension = mime.mid(mime.lastIndexOf(QLatin1Char(':')) + 1);
                        mime.chop(extension.length() + 1);
                        // Prepend '.' before extension, if required.
                        extension = extension.trimmed();
                        if (extension[0] != dot)
                            extension.prepend(dot);
                    }
                    if (!extension.isEmpty()) {
                        key = slash + extension;
                        settings->remove(key + QLatin1String("/Content Type"));
                        settings->remove(key + QLatin1String("/."));
                        settings->remove(key);
                        mime.replace(slash, QLatin1Char('\\'));
                        key = QLatin1String("/MIME/Database/Content Type/") + mime;
                        settings->remove(key + QLatin1String("/Extension"));
                        settings->remove(key + QLatin1String("/CLSID"));
                        settings->remove(key + QLatin1String("/."));
                        settings->remove(key);
                    }
                }
            }
            qCDebug(lcAxRegistration).nospace().noquote() << "Unregistered \""
                << progId << "\"/" << classId << ", \"" << file << "\" from \""
                << keyPath << '"';
        }
    }

    if (delete_qApp)
        delete qApp;

    qAxCleanup();
    if (settings->status() == QSettings::NoError)
        return S_OK;
    qWarning() << module << ": Error writing to " << keyPath;
    return SELFREG_E_CLASS;
}
Esempio n. 3
0
   virtual BOOL InitInstance() 
   { 
#ifdef CRASH_HANDLER
      rde::CrashHandler::Init();
#endif

      // disable auto-rotate on tablets
#if (WINVER <= 0x0601)
      SetDisplayAutoRotationPreferences = (pSDARP)GetProcAddress(GetModuleHandle(TEXT("user32.dll")),
         "SetDisplayAutoRotationPreferences");
      if (SetDisplayAutoRotationPreferences)
         SetDisplayAutoRotationPreferences(ORIENTATION_PREFERENCE_LANDSCAPE);
#else
      SetDisplayAutoRotationPreferences(ORIENTATION_PREFERENCE_LANDSCAPE);
#endif

      g_hinst = theInstance;
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
      hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
#else
      hRes = CoInitialize(NULL);
#endif
      _ASSERTE(SUCCEEDED(hRes));
      _Module.Init(ObjectMap, theInstance, &LIBID_VPinballLib);

      fFile = false;
      fPlay = false;
      fPov = false;
      bRun = true;
      int nRet = 0;
      memset(szTableFileName, 0, _MAX_PATH);
      // Start VP with file dialog open and then also playing that one?
      int stos;
      HRESULT hr = GetRegInt("Editor", "SelectTableOnStart", &stos);
      if (hr != S_OK)
         stos = 1; // The default = on
      if (stos)
      {
         fFile = true;
         fPlay = true;
         fPov = false;
      }

      int nArgs;
      LPSTR *szArglist = CommandLineToArgvA(GetCommandLine(), &nArgs);

      for (int i = 0; i < nArgs; ++i)
      {
         if (lstrcmpi(szArglist[i], _T("-h")) == 0 || lstrcmpi(szArglist[i], _T("/h")) == 0
            || lstrcmpi(szArglist[i], _T("-Help")) == 0 || lstrcmpi(szArglist[i], _T("/Help")) == 0
            || lstrcmpi(szArglist[i], _T("-?")) == 0 || lstrcmpi(szArglist[i], _T("/?")) == 0)
         {
            ShowError("-UnregServer  Unregister VP functions\n-RegServer  Register VP functions\n\n-DisableTrueFullscreen  Force-disable True Fullscreen setting\n\n-Edit [filename]  load file into VP\n-Play [filename]  load and play file\n-Pov [filename]  load, export pov and close");
            bRun = false;
            break;
         }

         if (lstrcmpi(szArglist[i], _T("-UnregServer")) == 0 || lstrcmpi(szArglist[i], _T("/UnregServer")) == 0)
         {
            _Module.UpdateRegistryFromResource(IDR_VPINBALL, FALSE);
            nRet = _Module.UnregisterServer(TRUE);
            bRun = false;
            break;
         }
         if (lstrcmpi(szArglist[i], _T("-RegServer")) == 0 || lstrcmpi(szArglist[i], _T("/RegServer")) == 0)
         {
            _Module.UpdateRegistryFromResource(IDR_VPINBALL, TRUE);
            nRet = _Module.RegisterServer(TRUE);
            bRun = false;
            break;
         }

         disableTrueFullscreen |= (lstrcmpi(szArglist[i], _T("-DisableTrueFullscreen")) == 0 || lstrcmpi(szArglist[i], _T("/DisableTrueFullscreen")) == 0);

         const bool editfile = (lstrcmpi(szArglist[i], _T("-Edit")) == 0 || lstrcmpi(szArglist[i], _T("/Edit")) == 0);
         const bool playfile = (lstrcmpi(szArglist[i], _T("-Play")) == 0 || lstrcmpi(szArglist[i], _T("/Play")) == 0);
		 const bool povfile = (lstrcmpi(szArglist[i], _T("-Pov")) == 0 || lstrcmpi(szArglist[i], _T("/Pov")) == 0);
		 if ((editfile || playfile || povfile) && (i + 1 < nArgs))
         {
            fFile = true;
            fPlay = playfile;
			fPov = povfile;

            // Remove leading - or /
            char* filename;
            if ((szArglist[i + 1][0] == '-') || (szArglist[i + 1][0] == '/'))
               filename = szArglist[i + 1] + 1;
            else
               filename = szArglist[i + 1];

            // Remove " "
            if (filename[0] == '"') {
               strcpy_s(szTableFileName, filename + 1);
               szTableFileName[lstrlen(szTableFileName) - 1] = '\0';
            }
            else
               strcpy_s(szTableFileName, filename);

            // Add current path
            char szLoadDir[MAX_PATH];
            if (szTableFileName[1] != ':') {
               GetCurrentDirectory(MAX_PATH, szLoadDir);
               strcat_s(szLoadDir, "\\");
               strcat_s(szLoadDir, szTableFileName);
               strcpy_s(szTableFileName, szLoadDir);
            }
            else
               // Or set from table path
               if (playfile) {
                  PathFromFilename(szTableFileName, szLoadDir);
                  SetCurrentDirectory(szLoadDir);
               }

            if (playfile || povfile)
               VPinball::SetOpenMinimized();

            break;
         }
      }

      free(szArglist);

      // load and register VP type library for COM integration
      char szFileName[_MAX_PATH];
      if (GetModuleFileName(theInstance, szFileName, _MAX_PATH))
      {
         ITypeLib *ptl = NULL;
         MAKE_WIDEPTR_FROMANSI(wszFileName, szFileName);
         if (SUCCEEDED(LoadTypeLib(wszFileName, &ptl)))
         {
            // first try to register system-wide (if running as admin)
            hr = RegisterTypeLib(ptl, wszFileName, NULL);
            if (!SUCCEEDED(hr))
            {
               // if failed, register only for current user
               hr = RegisterTypeLibForUser(ptl, wszFileName, NULL);
               if (!SUCCEEDED(hr))
                  MessageBox(0, "Could not register type library. Try running Visual Pinball as administrator.", "Error", MB_ICONWARNING);
            }
            ptl->Release();
         }
         else
            MessageBox(0, "Could not load type library.", "Error", MB_ICONSTOP);
      }

      //SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF );
      return TRUE;
   }