/** * Design Scripting Library * Copyright (C) 2004 Stylianos Dritsas * * This software is provided 'as-is', without any expressed or implied warranty. * In no event will the author be held liable for any damages arising from the * use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * * Stylianos Dritsas dritsas@alum.mit.edu * */ /** * BUILD INSTRUCTIONS: * compile with gcc / mingw * compile with: --add-stdcall-alias * linker with: libuuid.a, liboleaut32.a * * NOTICE: * Very few error checking, use with care :) * The DllUnregisterServer is totally unimplemented * The dll main is all over, as well as the lock server * and other boring to do methods * */ #include <windows.h> #include <initguid.h> #include <winreg.h> #ifndef INITGUID #define INITGUID #endif /** * Server GUID and hard coded dispatch interface info * to add methods: * 1. figure out the parameters and make another PARAMDATA entry * 2. put an entry in the interface table and !double check! the * disptch id and vtable index * 3. increment the interface table entries * 4. put the methods in the the binary file class in correct order * 5. implement the method! * */ /** * CLSID:32F5D805-FC94-4dde-8F25-960710BD6263 */ DEFINE_GUID( IID_DesignScripting, 0x32f5d805, 0xfc94, 0x4dde, 0x8f, 0x25, 0x96, 0x7, 0x10, 0xbd, 0x62, 0x63); #define DLLEXPORT __declspec( dllexport ) /** * Globals */ unsigned long global_references; bool global_lock; HINSTANCE global_instance; /** * Stupid param name Param type */ static PARAMDATA param_array = { OLESTR( "ARRAY" ), VT_BYREF | VT_VARIANT }; static PARAMDATA param_integer = { OLESTR( "INTEGER" ), VT_I4 }; static PARAMDATA param_real = { OLESTR( "REAL" ), VT_R8 }; static PARAMDATA param_file [2] = { { OLESTR( "STRING" ), VT_BSTR }, { OLESTR( "BOOLEAN" ), VT_BOOL } }; static PARAMDATA param_port [7] = { { OLESTR( "INTEGER" ), VT_I4 }, { OLESTR( "INTEGER" ), VT_I4 }, { OLESTR( "INTEGER" ), VT_I4 }, { OLESTR( "INTEGER" ), VT_I4 }, { OLESTR( "INTEGER" ), VT_I4 }, { OLESTR( "INTEGER" ), VT_I4 }, { OLESTR( "INTEGER" ), VT_I4 } }; /** * Name of the Method ParamList DispId #VTBL CallStyle #Params MethodCall ReturnType */ static METHODDATA method_table[] = { { OLESTR( "ABOUT" ), NULL, 100, 0, CC_CDECL, 0, DISPATCH_METHOD, VT_EMPTY }, { OLESTR( "OPENFILE" ), param_file, 1001, 1, CC_CDECL, 2, DISPATCH_METHOD, VT_BOOL }, { OLESTR( "OPENSERIAL" ), param_port, 1002, 2, CC_CDECL, 7, DISPATCH_METHOD, VT_BOOL }, { OLESTR( "CLOSE" ), NULL, 1003, 3, CC_CDECL, 0, DISPATCH_METHOD, VT_EMPTY }, { OLESTR( "READBYTE" ), NULL, 1004, 4, CC_CDECL, 0, DISPATCH_METHOD, VT_I4 }, { OLESTR( "READWORD" ), NULL, 1005, 5, CC_CDECL, 0, DISPATCH_METHOD, VT_I4 }, { OLESTR( "READDWORD" ), NULL, 1006, 6, CC_CDECL, 0, DISPATCH_METHOD, VT_I4 }, { OLESTR( "READSHORT" ), NULL, 1007, 7, CC_CDECL, 0, DISPATCH_METHOD, VT_I4 }, { OLESTR( "READLONG" ), NULL, 1008, 8, CC_CDECL, 0, DISPATCH_METHOD, VT_I4 }, { OLESTR( "READFLOAT" ), NULL, 1009, 9, CC_CDECL, 0, DISPATCH_METHOD, VT_R4 }, { OLESTR( "READDOUBLE" ), NULL, 1010, 10, CC_CDECL, 0, DISPATCH_METHOD, VT_R8 }, { OLESTR( "READBYTES" ), ¶m_array, 1011, 11, CC_CDECL, 1, DISPATCH_METHOD, VT_BOOL }, { OLESTR( "WRITEBYTE" ), ¶m_integer, 1012, 12, CC_CDECL, 1, DISPATCH_METHOD, VT_EMPTY }, { OLESTR( "WRITEWORD" ), ¶m_integer, 1013, 13, CC_CDECL, 1, DISPATCH_METHOD, VT_EMPTY }, { OLESTR( "WRITEDWORD" ), ¶m_integer, 1014, 14, CC_CDECL, 1, DISPATCH_METHOD, VT_EMPTY }, { OLESTR( "WRITESHORT" ), ¶m_integer, 1015, 15, CC_CDECL, 1, DISPATCH_METHOD, VT_EMPTY }, { OLESTR( "WRITELONG" ), ¶m_integer, 1016, 16, CC_CDECL, 1, DISPATCH_METHOD, VT_EMPTY }, { OLESTR( "WRITEFLOAT" ), ¶m_real, 1017, 17, CC_CDECL, 1, DISPATCH_METHOD, VT_EMPTY }, { OLESTR( "WRITEDOUBLE" ), ¶m_real, 1018, 18, CC_CDECL, 1, DISPATCH_METHOD, VT_EMPTY }, { OLESTR( "WRITEBYTES" ), ¶m_array, 1019, 19, CC_CDECL, 1, DISPATCH_METHOD, VT_BOOL }, { OLESTR( "LOCATION" ), NULL, 1020, 20, CC_CDECL, 0, DISPATCH_METHOD, VT_I4 }, { OLESTR( "MOVETO" ), ¶m_integer, 1021, 21, CC_CDECL, 1, DISPATCH_METHOD, VT_EMPTY }, { OLESTR( "LENGTH" ), NULL, 1022, 22, CC_CDECL, 0, DISPATCH_METHOD, VT_I4 } }; /** * Interface information */ INTERFACEDATA interface_table = { method_table, // methods info 23 // #methods }; /** * About message */ #define ABOUT_MESSAGE "DesignScripting Library version 1.0\r\n\r\nCopyright (c) 2004 Stylianos Dritsas\r\nAll rights reserved." class DesignScripting; /** * The method holder */ class BinaryFile { public: STDMETHOD_( void, About )( void ); STDMETHOD_( bool, OpenFile )( BSTR filename, BOOL readonly ); STDMETHOD_( bool, OpenSerial )( long portnumber, long buffersize, long baudrate, long parity, long databits, long stopbits, long timeout ); STDMETHOD_( void, Close )( void ); STDMETHOD_( long, ReadByte )( void ); STDMETHOD_( long, ReadWord )( void ); STDMETHOD_( long, ReadDWord )( void ); STDMETHOD_( long, ReadShort )( void ); STDMETHOD_( long, ReadLong )( void ); STDMETHOD_( float, ReadFloat )( void ); STDMETHOD_( double, ReadDouble )( void ); STDMETHOD_( bool, ReadBytes )( LPVARIANT ); STDMETHOD_( void, WriteByte )( long integer ); STDMETHOD_( void, WriteWord )( long integer ); STDMETHOD_( void, WriteDWord )( long integer ); STDMETHOD_( void, WriteShort )( long integer ); STDMETHOD_( void, WriteLong )( long integer ); STDMETHOD_( void, WriteFloat )( double real ); STDMETHOD_( void, WriteDouble )( double real ); STDMETHOD_( bool, WriteBytes )( LPVARIANT ); STDMETHOD_( long, Location )( void ); STDMETHOD_( void, MoveTo )( long integer ); STDMETHOD_( long, Length )( void ); BinaryFile( ) { this->designscripting = NULL; this->filehandle = INVALID_HANDLE_VALUE; } ~BinaryFile( ); public: DesignScripting* designscripting; HANDLE filehandle; }; /** * The unknown/dispatch handler */ class DesignScripting : public IUnknown { public: /** * On the fly idispatch */ static DesignScripting* Create( ) { ITypeInfo *typeinfo; IUnknown *dispatch; DesignScripting* scripting = new DesignScripting( ); scripting->AddRef( ); CreateDispTypeInfo( &interface_table, LOCALE_SYSTEM_DEFAULT, &typeinfo ); CreateStdDispatch( scripting, &( scripting->binaryfile ), typeinfo, &dispatch ); typeinfo->Release( ); scripting->unknown = dispatch; return scripting; } STDMETHOD ( QueryInterface )( REFIID riid, void **ppv ); STDMETHOD_( unsigned long, AddRef )( void ); STDMETHOD_( unsigned long, Release )( void ); DesignScripting( ) { this->binaryfile.designscripting = this; this->references = 0; } BinaryFile binaryfile; private: IUnknown* unknown; unsigned long references; }; /** * The class factory handler */ class DesignScriptingClassFactory : public IClassFactory { public: static IClassFactory* Create( ) { return new DesignScriptingClassFactory( ); } STDMETHOD ( QueryInterface )( REFIID riid, void **ppv ); STDMETHOD_( unsigned long, AddRef )( void ); STDMETHOD_( unsigned long, Release )( void ); STDMETHOD ( CreateInstance )( IUnknown *outer, REFIID id, void **ppv ); STDMETHOD ( LockServer )( BOOL lock ); DesignScriptingClassFactory( ) { this->references = 1; } private: unsigned long references; }; DesignScripting* designscripting; /******************************************************************************* * Implementation */ /** * Destructor */ BinaryFile::~BinaryFile( ) { if( this->filehandle != INVALID_HANDLE_VALUE ) { CloseHandle( this->filehandle ); } } /** * About */ STDMETHODIMP_( void ) BinaryFile::About( ) { MessageBox( NULL, ABOUT_MESSAGE, "About DesignScripting...", MB_OK | MB_ICONINFORMATION ); } /** * Open file stream */ STDMETHODIMP_( bool ) BinaryFile::OpenFile( BSTR filename, BOOL readonly ) { if( this->filehandle != INVALID_HANDLE_VALUE ) { CloseHandle( this->filehandle ); this->filehandle = INVALID_HANDLE_VALUE; } int length = WideCharToMultiByte( CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL ); char* buffer = new char[length]; WideCharToMultiByte( CP_ACP, 0, filename, -1, buffer, length, NULL, NULL ); this->filehandle = CreateFile( buffer, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, ( readonly ) ? OPEN_EXISTING : OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); delete[] buffer; return ( this->filehandle != INVALID_HANDLE_VALUE ); } /** * Open COM stream */ STDMETHODIMP_( bool ) BinaryFile::OpenSerial( long portnumber, long buffersize, long baudrate, long parity, long databits, long stopbits, long timeout ) { if( this->filehandle != INVALID_HANDLE_VALUE ) { CloseHandle( this->filehandle ); this->filehandle = INVALID_HANDLE_VALUE; } char* DeviceName = new char[256]; wsprintf( DeviceName, "COM%d\0", portnumber ); this->filehandle = CreateFile( DeviceName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, NULL ); if( this->filehandle != INVALID_HANDLE_VALUE ) { delete[] DeviceName; return false; } delete[] DeviceName; if( SetupComm( this->filehandle, buffersize, buffersize ) == 0 ) { CloseHandle( this->filehandle ); this->filehandle = INVALID_HANDLE_VALUE; return false; } DCB state; if( GetCommState( this->filehandle, &state ) == 0 ) { CloseHandle( this->filehandle ); this->filehandle = INVALID_HANDLE_VALUE; return false; } char* config = new char[256]; wsprintf( config, "baud=%d parity=%s data=%d stop=%d\0", baudrate, ( parity != 0 ) ? "y" : "n", databits, stopbits ); if( BuildCommDCB( config, &state ) == 0 ) { delete[] config; CloseHandle( this->filehandle ); this->filehandle = INVALID_HANDLE_VALUE; return false; } delete[] config; if( SetCommState( this->filehandle, &state ) == 0 ) { CloseHandle( this->filehandle ); this->filehandle = INVALID_HANDLE_VALUE; return false; } COMMTIMEOUTS timeouts; timeouts.ReadIntervalTimeout = 0; timeouts.ReadTotalTimeoutMultiplier = 0; timeouts.ReadTotalTimeoutConstant = timeout; timeouts.WriteTotalTimeoutMultiplier = 0; timeouts.WriteTotalTimeoutConstant = timeout; if( SetCommTimeouts( this->filehandle, &timeouts ) == 0 ) { CloseHandle( this->filehandle ); this->filehandle = INVALID_HANDLE_VALUE; return false; } return true; } /** * Write bytes to stream */ STDMETHODIMP_( bool ) BinaryFile::WriteBytes( LPVARIANT array ) { BYTE* bytes; DWORD count, size; if( this->filehandle == INVALID_HANDLE_VALUE ) { return false; } if( array->vt != ( VT_ARRAY | VT_VARIANT ) ) { return false; } if( array->parray == NULL ) { return false; } if( array->parray->cDims != 1 ) { return false; } long lbound, ubound; if( FAILED( SafeArrayGetLBound( array->parray, 1, &lbound )) || FAILED( SafeArrayGetUBound( array->parray, 1, &ubound ) ) ) { return false; } long item = 0; count = ubound - lbound + 1; bytes = (BYTE *)malloc( count ); if( bytes == NULL ) { return false; } VARIANT element; for( long index = lbound; index <= ubound; index++ ) { if( FAILED( SafeArrayGetElement( array->parray, &index, &element ) ) ) { free( bytes ); return false; } else { switch( element.vt ) { case VT_UI1: bytes[item++] = (BYTE)element.bVal; break; case VT_I2: bytes[item++] = (BYTE)element.iVal; break; case VT_I4: bytes[item++] = (BYTE)element.lVal; break; default: bytes[item++] = 0; } } } if( WriteFile( this->filehandle, bytes, count, &size, NULL ) ) { free( bytes ); return true; } else { free( bytes ); return false; } } /** * Read bytes from stream */ STDMETHODIMP_( bool ) BinaryFile::ReadBytes( LPVARIANT array ) { BYTE* bytes; DWORD count, size; if( this->filehandle == INVALID_HANDLE_VALUE ) { return false; } if( array->vt != ( VT_ARRAY | VT_VARIANT ) ) { return false; } if( array->parray == NULL ) { return false; } if( array->parray->cDims != 1 ) { return false; } long lbound, ubound; if( FAILED( SafeArrayGetLBound( array->parray, 1, &lbound )) || FAILED( SafeArrayGetUBound( array->parray, 1, &ubound ) ) ) { return false; } long item = 0; count = ubound - lbound + 1; bytes = (BYTE *)malloc( count ); if( bytes == NULL ) { return false; } if( !ReadFile( this->filehandle, bytes, count, &size, NULL ) ) { free( bytes ); return false; } VARIANT element; for( long index = lbound; index <= ubound; index++ ) { if( FAILED( SafeArrayGetElement( array->parray, &index, &element ) ) ) { free( bytes ); return false; } else { switch( element.vt ) { case VT_UI1: element.bVal = bytes[item++]; break; case VT_I2: element.iVal = bytes[item++]; break; case VT_I4: element.lVal = bytes[item++]; break; } if( FAILED( SafeArrayPutElement( array->parray, &index, &element ) ) ) { free( bytes ); return false; } } } free( bytes ); return true; } /** * Close stream */ STDMETHODIMP_( void ) BinaryFile::Close( ) { if( this->filehandle != INVALID_HANDLE_VALUE ) { CloseHandle( this->filehandle ); } } /** * Read a byte */ STDMETHODIMP_( long ) BinaryFile::ReadByte( ) { DWORD bytes; BYTE buffer; if( this->filehandle != INVALID_HANDLE_VALUE ) { ReadFile( this->filehandle, &buffer, sizeof( buffer ), &bytes, NULL ); return buffer; } else { return -1; } } /** * Read a word */ STDMETHODIMP_( long ) BinaryFile::ReadWord( ) { DWORD bytes; WORD buffer; if( this->filehandle != INVALID_HANDLE_VALUE ) { ReadFile( this->filehandle, &buffer, sizeof( buffer ), &bytes, NULL ); return buffer; } else { return -1; } } /** * Read a double word */ STDMETHODIMP_( long ) BinaryFile::ReadDWord( ) { DWORD bytes; DWORD buffer; if( this->filehandle != INVALID_HANDLE_VALUE ) { ReadFile( this->filehandle, &buffer, sizeof( buffer ), &bytes, NULL ); return buffer; } else { return -1; } } /** * Read a short int */ STDMETHODIMP_( long ) BinaryFile::ReadShort( ) { DWORD bytes; short buffer; if( this->filehandle != INVALID_HANDLE_VALUE ) { ReadFile( this->filehandle, &buffer, sizeof( buffer ), &bytes, NULL ); return buffer; } else { return -1; } } /** * Read a long int */ STDMETHODIMP_( long ) BinaryFile::ReadLong( ) { DWORD bytes; long buffer; if( this->filehandle != INVALID_HANDLE_VALUE ) { ReadFile( this->filehandle, &buffer, sizeof( buffer ), &bytes, NULL ); return buffer; } else { return -1; } } /** * Read a float */ STDMETHODIMP_( float ) BinaryFile::ReadFloat( ) { DWORD bytes; float buffer; if( this->filehandle != INVALID_HANDLE_VALUE ) { ReadFile( this->filehandle, &buffer, sizeof( buffer ), &bytes, NULL ); return buffer; } else { return -1; } } /** * Read a double */ STDMETHODIMP_( double ) BinaryFile::ReadDouble( ) { DWORD bytes; double buffer; if( this->filehandle != INVALID_HANDLE_VALUE ) { ReadFile( this->filehandle, &buffer, sizeof( buffer ), &bytes, NULL ); return buffer; } else { return -1; } } /** * Write a byte */ STDMETHODIMP_( void ) BinaryFile::WriteByte( long integer ) { DWORD bytes; BYTE buffer = (BYTE)integer; if( this->filehandle != INVALID_HANDLE_VALUE ) { WriteFile( this->filehandle, &buffer, sizeof( buffer ), &bytes, NULL ); } } /** * Write a word */ STDMETHODIMP_( void ) BinaryFile::WriteWord( long integer ) { DWORD bytes; WORD buffer = (WORD)integer; if( this->filehandle != INVALID_HANDLE_VALUE ) { WriteFile( this->filehandle, &buffer, sizeof( buffer ), &bytes, NULL ); } } /** * Write a double word */ STDMETHODIMP_( void ) BinaryFile::WriteDWord( long integer ) { DWORD bytes; DWORD buffer = (DWORD)integer; if( this->filehandle != INVALID_HANDLE_VALUE ) { WriteFile( this->filehandle, &buffer, sizeof( buffer ), &bytes, NULL ); } } /** * Write a short int */ STDMETHODIMP_( void ) BinaryFile::WriteShort( long integer ) { DWORD bytes; short buffer = (WORD)integer; if( this->filehandle != INVALID_HANDLE_VALUE ) { WriteFile( this->filehandle, &buffer, sizeof( buffer ), &bytes, NULL ); } } /** * Write a long int */ STDMETHODIMP_( void ) BinaryFile::WriteLong( long integer ) { DWORD bytes; long buffer = (DWORD)integer; if( this->filehandle != INVALID_HANDLE_VALUE ) { WriteFile( this->filehandle, &buffer, sizeof( buffer ), &bytes, NULL ); } } /** * Write a float */ STDMETHODIMP_( void ) BinaryFile::WriteFloat( double real ) { DWORD bytes; float buffer = (float)real; if( this->filehandle != INVALID_HANDLE_VALUE ) { WriteFile( this->filehandle, &buffer, sizeof( buffer ), &bytes, NULL ); } } /** * Write a double */ STDMETHODIMP_( void ) BinaryFile::WriteDouble( double real ) { DWORD bytes; double buffer = real; if( this->filehandle != INVALID_HANDLE_VALUE ) { WriteFile( this->filehandle, &buffer, sizeof( buffer ), &bytes, NULL ); } } /** * Stream location */ STDMETHODIMP_( long ) BinaryFile::Location( ) { if( this->filehandle != INVALID_HANDLE_VALUE ) { return SetFilePointer( this->filehandle, 0, NULL, FILE_CURRENT ); } else { return -1; } } /** * Stream seek */ STDMETHODIMP_( void ) BinaryFile::MoveTo( long integer ) { if( this->filehandle != INVALID_HANDLE_VALUE ) { SetFilePointer( this->filehandle, integer, NULL, FILE_BEGIN ); } } /** * Stream length */ STDMETHODIMP_( long ) BinaryFile::Length( ) { if( this->filehandle != INVALID_HANDLE_VALUE ) { long save = SetFilePointer( this->filehandle, 0, NULL, FILE_CURRENT ); long length = SetFilePointer( this->filehandle, 0, NULL, FILE_END ); SetFilePointer( this->filehandle, save, NULL, FILE_BEGIN ); return length; } else { return -1; } } /** * IUknown stuff */ STDMETHODIMP DesignScripting::QueryInterface( REFIID id, void **ppv ) { if( IsEqualIID( id, IID_IUnknown ) ) { *ppv = this; } else if( IsEqualIID( id, IID_IDispatch ) ) { return this->unknown->QueryInterface( id, ppv ); } else { *ppv = NULL; return ResultFromScode( E_NOINTERFACE ); } this->AddRef( ); return NOERROR; } /** * IUknown stuff */ STDMETHODIMP_(unsigned long) DesignScripting::AddRef( ) { return ++this->references; } /** * IUknown stuff */ STDMETHODIMP_(unsigned long) DesignScripting::Release( ) { if( ( --this->references ) == 0 ) { if( this->unknown != NULL ) { this->unknown->Release( ); } delete this; return 0; } else { return this->references; } } /** * IUknown stuff */ STDMETHODIMP DesignScriptingClassFactory::QueryInterface( REFIID id, void **ppv ) { if( IsEqualIID( id, IID_IUnknown ) || IsEqualIID( id, IID_IClassFactory ) ) { this->AddRef( ); *ppv = this; return NOERROR; } else { *ppv = NULL; return ResultFromScode( E_NOINTERFACE ); } } /** * IUknown stuff */ STDMETHODIMP_(unsigned long) DesignScriptingClassFactory::AddRef( ) { return this->references++; } /** * IUknown stuff */ STDMETHODIMP_(unsigned long) DesignScriptingClassFactory::Release( ) { if( ( --this->references ) == 0 ) { delete this; return 0; } else { return this->references; } } /** * IClassFactory stuff */ STDMETHODIMP DesignScriptingClassFactory::CreateInstance( IUnknown *outer, REFIID id, void **ppv ) { if( outer != NULL ) { return ResultFromScode( CLASS_E_NOAGGREGATION ); } else { DesignScripting* designscripting = DesignScripting::Create( ); return designscripting->QueryInterface( id, ppv ); } } /** * IClassFactory stuff */ STDMETHODIMP DesignScriptingClassFactory::LockServer( BOOL lock ) { return( NOERROR ); } /** * Library stuff */ STDAPI DLLEXPORT DllGetClassObject( const CLSID& rclsid, const IID& riid, void ** ppv ) { if( !IsEqualGUID( rclsid, IID_DesignScripting ) ) { return( E_FAIL ); } if( ( !IsEqualGUID( riid, IID_IUnknown ) ) && ( !IsEqualGUID( riid, IID_IClassFactory ) ) ) { return( E_NOINTERFACE ); } *ppv = new DesignScriptingClassFactory( ); if( *ppv == NULL ) { return( E_OUTOFMEMORY ); } ( (IUnknown*)*ppv )->AddRef( ); return( S_OK ); } /** * Library stuff */ STDAPI DLLEXPORT DllCanUnloadNow( ) { return( S_OK ); } /** * Library stuff */ STDAPI DLLEXPORT DllRegisterServer( ) { char STR_DESIGNSCRIPTING[] = "DesignScripting\0"; char STR_CLASSID[] = "{32F5D805-FC94-4DDE-8F25-960710BD6263}\0"; char STR_THREADINGMODEL[] = "ThreadingModel\0"; char STR_APPARTMENT[] = "Apartment\0"; char STR_FOLDER[512]; HKEY keya, keyb, keyc; if( RegCreateKey( HKEY_CLASSES_ROOT, TEXT("DesignScripting"), &keya ) != ERROR_SUCCESS ) { return E_UNEXPECTED; } if( RegSetValue( keya, NULL, REG_SZ, STR_DESIGNSCRIPTING, sizeof( STR_DESIGNSCRIPTING ) ) != ERROR_SUCCESS ) { RegCloseKey( keya ); return E_UNEXPECTED; } if( RegCreateKey( keya, TEXT("CLSID"), &keyb ) != ERROR_SUCCESS ) { RegCloseKey( keya ); return E_UNEXPECTED; } if( RegSetValue( keyb, NULL, REG_SZ, STR_CLASSID, sizeof( STR_CLASSID ) ) != ERROR_SUCCESS ) { RegCloseKey( keya ); RegCloseKey( keyb ); return E_UNEXPECTED; } RegCloseKey( keya ); RegCloseKey( keyb ); if( RegCreateKey( HKEY_CLASSES_ROOT, TEXT("CLSID"), &keya ) != ERROR_SUCCESS ) { return E_UNEXPECTED; } if( RegCreateKey( keya, STR_CLASSID, &keyb ) != ERROR_SUCCESS ) { RegCloseKey( keya ); return E_UNEXPECTED; } if( RegSetValue( keyb, NULL, REG_SZ, STR_DESIGNSCRIPTING, sizeof( STR_DESIGNSCRIPTING ) ) != ERROR_SUCCESS ) { RegCloseKey( keya ); RegCloseKey( keyb ); return E_UNEXPECTED; } if( RegCreateKey( keyb, TEXT("InProcServer32"), &keyc ) != ERROR_SUCCESS ) { RegCloseKey( keya ); RegCloseKey( keyb ); return E_UNEXPECTED; } if( GetModuleFileName( global_instance, STR_FOLDER, sizeof( STR_FOLDER ) / sizeof( TCHAR ) ) == 0 ) { RegCloseKey( keya ); RegCloseKey( keyb ); RegCloseKey( keyc ); return E_UNEXPECTED; } if( RegSetValue( keyc, NULL, REG_SZ, STR_FOLDER, lstrlen( STR_FOLDER ) ) != ERROR_SUCCESS ) { RegCloseKey( keya ); RegCloseKey( keyb ); RegCloseKey( keyc ); return E_UNEXPECTED; } if( RegSetValueEx( keyc, STR_THREADINGMODEL, 0, REG_SZ, (BYTE*)STR_APPARTMENT, sizeof( STR_APPARTMENT ) ) != ERROR_SUCCESS ) { RegCloseKey( keya ); RegCloseKey( keyb ); RegCloseKey( keyc ); return E_UNEXPECTED; } RegCloseKey( keyc ); if( RegCreateKey( keyb, TEXT("ProgID"), &keyc ) != ERROR_SUCCESS ) { RegCloseKey( keya ); RegCloseKey( keyb ); return E_UNEXPECTED; } if( RegSetValue( keyc, NULL, REG_SZ, STR_DESIGNSCRIPTING, sizeof( STR_DESIGNSCRIPTING ) ) != ERROR_SUCCESS ) { RegCloseKey( keya ); RegCloseKey( keyb ); RegCloseKey( keyc ); return E_UNEXPECTED; } RegCloseKey( keyc ); if( RegCreateKey( keyb, TEXT("VersionIndependentProgID"), &keyc ) != ERROR_SUCCESS ) { RegCloseKey( keya ); RegCloseKey( keyb ); return E_UNEXPECTED; } if( RegSetValue( keyc, NULL, REG_SZ, STR_DESIGNSCRIPTING, sizeof( STR_DESIGNSCRIPTING ) ) != ERROR_SUCCESS ) { RegCloseKey( keya ); RegCloseKey( keyb ); RegCloseKey( keyc ); return E_UNEXPECTED; } RegCloseKey( keya ); RegCloseKey( keyb ); RegCloseKey( keyc ); return( S_OK ); } /** * Library stuff */ STDAPI DLLEXPORT DllUnregisterServer( ) { return( E_UNEXPECTED ); } /** * Old time library stuff */ extern "C" { BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved ) { global_references = 0; global_lock = false; global_instance = hInst; return TRUE; } }