home *** CD-ROM | disk | FTP | other *** search
/ Planet Source Code Jumbo …e CD Visual Basic 1 to 7 / 5_2007-2008.ISO / data / Zips / Plugin_Fra2028191112006.psc / PluginLoader.cls < prev    next >
Text File  |  2006-10-28  |  16KB  |  560 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4.   Persistable = 0  'NotPersistable
  5.   DataBindingBehavior = 0  'vbNone
  6.   DataSourceBehavior  = 0  'vbNone
  7.   MTSTransactionMode  = 0  'NotAnMTSObject
  8. END
  9. Attribute VB_Name = "PlugInLoader"
  10. Attribute VB_GlobalNameSpace = False
  11. Attribute VB_Creatable = True
  12. Attribute VB_PredeclaredId = False
  13. Attribute VB_Exposed = False
  14. Option Explicit
  15.  
  16. Private Declare Function LoadLibrary Lib "kernel32" _
  17. Alias "LoadLibraryA" ( _
  18.     ByVal lpszLib As String _
  19. ) As Long
  20.  
  21. Private Declare Function FreeLibrary Lib "kernel32" ( _
  22.     ByVal hMod As Long _
  23. ) As Long
  24.  
  25. Private Declare Function GetProcAddress Lib "kernel32" ( _
  26.     ByVal hMod As Long, _
  27.     ByVal lpszFnc As String _
  28. ) As Long
  29.  
  30. Private Declare Function CallWindowProc Lib "user32" _
  31. Alias "CallWindowProcA" ( _
  32.     ByVal lpPrevWndFunc As Long, _
  33.     ByVal hWnd As Long, _
  34.     ByVal Msg As Long, _
  35.     ByVal wParam As Long, _
  36.     ByVal lParam As Long _
  37. ) As Long
  38.  
  39. Private Declare Function VirtualAlloc Lib "kernel32" ( _
  40.     ByVal lpAddress As Long, _
  41.     ByVal dwSize As Long, _
  42.     ByVal flAllocType As Long, _
  43.     ByVal flProtect As Long _
  44. ) As Long
  45.  
  46. Private Declare Function VirtualFree Lib "kernel32" ( _
  47.     ByVal lpAddress As Long, _
  48.     ByVal dwSize As Long, _
  49.     ByVal dwFreeType As Long _
  50. ) As Long
  51.  
  52. Private Declare Function VirtualProtect Lib "kernel32" ( _
  53.     ByVal lpAddress As Long, _
  54.     ByVal dwSize As Long, _
  55.     ByVal flNewProtect As Long, _
  56.     lpflOldProtect As Long _
  57. ) As Long
  58.  
  59. Private Declare Sub CpyMem Lib "kernel32" _
  60. Alias "RtlMoveMemory" ( _
  61.     pDst As Any, _
  62.     pSrc As Any, _
  63.     ByVal cBytes As Long _
  64. )
  65.  
  66. Private Declare Function FindFirstFile Lib "kernel32" _
  67. Alias "FindFirstFileA" ( _
  68.     ByVal lpFileName As String, _
  69.     lpFindFileData As WIN32_FIND_DATA _
  70. ) As Long
  71.  
  72. Private Declare Function FindNextFile Lib "kernel32" _
  73. Alias "FindNextFileA" ( _
  74.     ByVal hFindFile As Long, _
  75.     lpFindFileData As WIN32_FIND_DATA _
  76. ) As Long
  77.  
  78. Private Declare Function GetFileAttributes Lib "kernel32" _
  79. Alias "GetFileAttributesA" ( _
  80.     ByVal lpFileName As String _
  81. ) As Long
  82.  
  83. Private Declare Function FindClose Lib "kernel32" ( _
  84.     ByVal hFindFile As Long _
  85. ) As Long
  86.  
  87. Private Const MAX_PATH                  As Long = 260
  88. Private Const MAXDWORD                  As Long = &HFFFF
  89. Private Const FILE_ATTRIBUTE_ARCHIVE    As Long = &H20
  90. Private Const FILE_ATTRIBUTE_DIRECTORY  As Long = &H10
  91. Private Const FILE_ATTRIBUTE_HIDDEN     As Long = &H2
  92. Private Const FILE_ATTRIBUTE_NORMAL     As Long = &H80
  93. Private Const FILE_ATTRIBUTE_READONLY   As Long = &H1
  94. Private Const FILE_ATTRIBUTE_SYSTEM     As Long = &H4
  95. Private Const FILE_ATTRIBUTE_TEMPORARY  As Long = &H100
  96. Private Const INVALID_HANDLE            As Long = -1
  97.  
  98. Private Enum VirtualFreeTypes
  99.     MEM_DECOMMIT = &H4000
  100.     MEM_RELEASE = &H8000
  101. End Enum
  102.  
  103. Private Enum VirtualAllocTypes
  104.     MEM_COMMIT = &H1000
  105.     MEM_RESERVE = &H2000
  106.     MEM_RESET = &H8000
  107.     MEM_LARGE_PAGES = &H20000000
  108.     MEM_PHYSICAL = &H100000
  109.     MEM_WRITE_WATCH = &H200000
  110. End Enum
  111.  
  112. Private Enum VirtualAllocPageFlags
  113.     PAGE_EXECUTE = &H10
  114.     PAGE_EXECUTE_READ = &H20
  115.     PAGE_EXECUTE_READWRITE = &H40
  116.     PAGE_EXECUTE_WRITECOPY = &H80
  117.     PAGE_NOACCESS = &H1
  118.     PAGE_READONLY = &H2
  119.     PAGE_READWRITE = &H4
  120.     PAGE_WRITECOPY = &H8
  121.     PAGE_GUARD = &H100
  122.     PAGE_NOCACHE = &H200
  123.     PAGE_WRITECOMBINE = &H400
  124. End Enum
  125.  
  126. Private Type allocated_memory
  127.     address     As Long
  128.     bytes       As Long
  129. End Type
  130.  
  131. Private Type FILETIME
  132.     dwLowDateTime               As Long
  133.     dwHighDateTime              As Long
  134. End Type
  135.  
  136. Private Type WIN32_FIND_DATA
  137.     dwFileAttributes            As Long
  138.     FTCreationTime              As FILETIME
  139.     FTLastAccessTime            As FILETIME
  140.     FTLastWriteTime             As FILETIME
  141.     nFileSizeHigh               As Long
  142.     nFileSizeLow                As Long
  143.     dwReserved0                 As Long
  144.     dwReserved1                 As Long
  145.     cFileName                   As String * MAX_PATH
  146.     cAlternate                  As String * 14
  147. End Type
  148.  
  149. Private Type PluginClass
  150.     localfile                   As String
  151.     guid                        As UUID
  152. End Type
  153.  
  154. Private clsInterface            As olelib.IDispatch
  155. Private uidInterface            As UUID
  156. Private strPlugPath             As String
  157. Private strFilter               As String
  158. Private blnRecursive            As Boolean
  159.  
  160. Private udtPlugins()            As PluginClass
  161. Private lngPluginCnt            As Long
  162.  
  163. Public Property Get PluginCount() As Long
  164.     PluginCount = lngPluginCnt
  165. End Property
  166.  
  167. Public Property Get PluginLocation(ByVal index As Long) As String
  168.     If PluginCount = 0 Then Err.Raise 9
  169.     PluginLocation = udtPlugins(index).localfile
  170. End Property
  171.  
  172. Public Function CreatePlugin(ByVal index As Long) As olelib.IUnknown
  173.     Dim iunkPlugin  As olelib.IUnknown
  174.  
  175.     If PluginCount = 0 Then Err.Raise 9
  176.  
  177.     CoCreateInstance udtPlugins(index).guid, _
  178.                      Nothing, _
  179.                      CLSCTX_INPROC_SERVER, _
  180.                      uidInterface, _
  181.                      iunkPlugin
  182.  
  183.     Set CreatePlugin = iunkPlugin
  184. End Function
  185.  
  186. Public Function FindPlugins() As Long
  187.     Dim strExts() As String
  188.  
  189.     lngPluginCnt = 0
  190.     strExts = Split(strFilter, ";")
  191.  
  192.     FindFilesAPI strPlugPath, strExts, True
  193.  
  194.     FindPlugins = lngPluginCnt
  195. End Function
  196.  
  197. Public Property Get filter() As String
  198.     filter = strFilter
  199. End Property
  200.  
  201. Public Property Let filter(ByVal strF As String)
  202.     strFilter = strF
  203. End Property
  204.  
  205. Public Property Get Interface() As olelib.IDispatch
  206.     Set Interface = clsInterface
  207. End Property
  208.  
  209. Public Property Set Interface(clsIdisp As olelib.IDispatch)
  210.     Set clsInterface = clsIdisp
  211.     uidInterface = IIDfromDispatch(clsInterface)
  212. End Property
  213.  
  214. Public Property Get PluginPath() As String
  215.     PluginPath = strPlugPath
  216. End Property
  217.  
  218. Public Property Let PluginPath(ByVal strPath As String)
  219.     strPlugPath = strPath
  220. End Property
  221.  
  222. Public Property Get RecursiveSearch() As Boolean
  223.     RecursiveSearch = blnRecursive
  224. End Property
  225.  
  226. Public Property Let RecursiveSearch(ByVal blnVal As Boolean)
  227.     blnRecursive = blnVal
  228. End Property
  229.  
  230. Private Function DirExists(ByVal DirName As String) As Boolean
  231.     On Error Resume Next
  232.     DirExists = GetAttr(DirName) And vbDirectory
  233. End Function
  234.  
  235. Private Function AddSlash(ByVal strText As String) As String
  236.     AddSlash = IIf(Right$(strText, 1) = "\", strText, strText & "\")
  237. End Function
  238.  
  239. Private Sub Class_Initialize()
  240.     If DirExists(AddSlash(App.path) & "plugins") Then
  241.         strPlugPath = AddSlash(App.path) & "plugins"
  242.     Else
  243.         strPlugPath = AddSlash(App.path)
  244.     End If
  245.  
  246.     blnRecursive = True
  247.  
  248.     strFilter = "*.dll;*.ocx"
  249. End Sub
  250.  
  251. Private Sub FindFilesAPI( _
  252.     ByVal path As String, _
  253.     filter() As String, _
  254.     ByVal recursive As Boolean _
  255. )
  256.  
  257.     Dim hSearch     As Long
  258.     Dim udtFindData As WIN32_FIND_DATA
  259.     Dim lngRet      As Long
  260.     Dim i           As Long
  261.     Dim uid         As UUID
  262.     Dim strPFile    As String
  263.  
  264.     If Not Right$(path, 1) = "\" Then path = path & "\"
  265.  
  266.     hSearch = FindFirstFile(path & "*.*", udtFindData)
  267.     If hSearch = INVALID_HANDLE Then Exit Sub
  268.  
  269.     If Left$(udtFindData.cFileName, 1) <> "." Then
  270.         If (udtFindData.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then
  271.             If recursive Then
  272.                 FindFilesAPI path & Trim$(StripNulls(udtFindData.cFileName)), filter, recursive
  273.             End If
  274.         Else
  275.             For i = LBound(filter) To UBound(filter)
  276.                 If StripNulls(udtFindData.cFileName) Like filter(i) Then
  277.                     strPFile = path & Trim$(StripNulls(udtFindData.cFileName))
  278.  
  279.                     If IsValidPlugin(strPFile, uid) Then
  280.                         ReDim Preserve udtPlugins(lngPluginCnt) As PluginClass
  281.                         udtPlugins(lngPluginCnt).localfile = strPFile
  282.                         udtPlugins(lngPluginCnt).guid = uid
  283.                         lngPluginCnt = lngPluginCnt + 1
  284.                     End If
  285.                     Exit For
  286.                 End If
  287.             Next
  288.         End If
  289.     End If
  290.  
  291.     lngRet = 1
  292.  
  293.     Do
  294.         lngRet = FindNextFile(hSearch, udtFindData)
  295.         If lngRet = 0 Then Exit Do
  296.  
  297.         If Left$(udtFindData.cFileName, 1) <> "." Then
  298.             If (udtFindData.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then
  299.                 If recursive Then
  300.                     FindFilesAPI path & Trim$(StripNulls(udtFindData.cFileName)), filter, recursive
  301.                 End If
  302.             Else
  303.                 For i = LBound(filter) To UBound(filter)
  304.                     If StripNulls(udtFindData.cFileName) Like filter(i) Then
  305.                         strPFile = path & Trim$(StripNulls(udtFindData.cFileName))
  306.  
  307.                         If IsValidPlugin(strPFile, uid) Then
  308.                             ReDim Preserve udtPlugins(lngPluginCnt) As PluginClass
  309.                             udtPlugins(lngPluginCnt).localfile = strPFile
  310.                             udtPlugins(lngPluginCnt).guid = uid
  311.                             lngPluginCnt = lngPluginCnt + 1
  312.                         End If
  313.                         Exit For
  314.                     End If
  315.                 Next
  316.             End If
  317.         End If
  318.     Loop
  319.  
  320.     FindClose hSearch
  321. End Sub
  322.  
  323. Private Function StripNulls( _
  324.     OriginalStr As String _
  325. ) As String
  326.  
  327.     If InStr(OriginalStr, Chr(0)) > 0 Then
  328.         OriginalStr = Left(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)
  329.     End If
  330.  
  331.     StripNulls = Trim$(OriginalStr)
  332. End Function
  333.  
  334. Private Function IsValidPlugin( _
  335.     ByVal strFile As String, _
  336.     classguid As UUID _
  337. ) As Boolean
  338.  
  339.     Dim clsTypeLib  As ITypeLib
  340.     Dim clsTypeInfo As ITypeInfo
  341.     Dim clsImplInfo As ITypeInfo
  342.     Dim pTypeAttr   As Long
  343.     Dim udtTypeAttr As TYPEATTR
  344.     Dim udtImplAttr As TYPEATTR
  345.     Dim i           As Long
  346.     Dim j           As Long
  347.     Dim hRefType    As Long
  348.  
  349.     ' first register the component, then try to load its type library
  350.     If Not RegisterServer(strFile, True) Then Exit Function
  351.  
  352.     Set clsTypeLib = LoadTypeLibEx(strFile, REGKIND_REGISTER)
  353.     If clsTypeLib Is Nothing Then Exit Function
  354.  
  355.     ' get all the CoClasses in the server and search for
  356.     ' the interface the plugins have to implement
  357.     For i = 0 To clsTypeLib.GetTypeInfoCount - 1
  358.         If clsTypeLib.GetTypeInfoType(i) = TKIND_COCLASS Then
  359.             Set clsTypeInfo = clsTypeLib.GetTypeInfo(i)
  360.  
  361.             pTypeAttr = clsTypeInfo.GetTypeAttr
  362.             If pTypeAttr <> 0 Then
  363.                 CpyMem udtTypeAttr, ByVal pTypeAttr, Len(udtTypeAttr)
  364.                 clsTypeInfo.ReleaseTypeAttr pTypeAttr
  365.  
  366.                 ' Implements of the current class
  367.                 For j = 0 To udtTypeAttr.cImplTypes - 1
  368.                     hRefType = clsTypeInfo.GetRefTypeOfImplType(j)
  369.                     Set clsImplInfo = clsTypeInfo.GetRefTypeInfo(hRefType)
  370.  
  371.                     If Not clsImplInfo Is Nothing Then
  372.                         pTypeAttr = clsImplInfo.GetTypeAttr
  373.                         If pTypeAttr <> 0 Then
  374.                             CpyMem udtImplAttr, ByVal pTypeAttr, Len(udtImplAttr)
  375.                             clsImplInfo.ReleaseTypeAttr pTypeAttr
  376.  
  377.                             If CompareGUIDs(udtImplAttr.iid, uidInterface) Then
  378.                                 ' a class implements the specified interface,
  379.                                 ' we found a plugin!
  380.                                 classguid = udtTypeAttr.iid
  381.                                 IsValidPlugin = True
  382.                                 Exit Function
  383.                             End If
  384.  
  385.                         End If
  386.                     End If
  387.  
  388.                 Next
  389.  
  390.             End If
  391.         End If
  392.     Next
  393. End Function
  394.  
  395. Private Function CompareGUIDs( _
  396.     guid1 As UUID, _
  397.     guid2 As UUID _
  398. ) As Boolean
  399.  
  400.     Dim i   As Long
  401.  
  402.     If guid1.Data1 = guid2.Data1 Then
  403.         If guid1.Data2 = guid2.Data2 Then
  404.             If guid1.Data3 = guid2.Data3 Then
  405.                 For i = 0 To 7
  406.                     If guid1.Data4(i) <> guid2.Data4(i) Then
  407.                         Exit Function
  408.                     End If
  409.                 Next
  410.  
  411.                 CompareGUIDs = True
  412.             End If
  413.         End If
  414.     End If
  415. End Function
  416.  
  417. Private Function IIDfromDispatch( _
  418.     clsDisp As olelib.IDispatch _
  419. ) As UUID
  420.  
  421.     Dim pTypeAttr   As Long
  422.     Dim udtTypeAttr As TYPEATTR
  423.  
  424.     pTypeAttr = clsDisp.GetTypeInfo.GetTypeAttr
  425.  
  426.     If pTypeAttr = 0 Then Exit Function
  427.     CpyMem udtTypeAttr, ByVal pTypeAttr, Len(udtTypeAttr)
  428.  
  429.     IIDfromDispatch = udtTypeAttr.iid
  430.  
  431.     clsDisp.GetTypeInfo.ReleaseTypeAttr pTypeAttr
  432. End Function
  433.  
  434. Private Function RegisterServer( _
  435.     ByVal strFile As String, _
  436.     ByVal register As Boolean _
  437. ) As Boolean
  438.  
  439.     Dim hLib    As Long
  440.     Dim fpReg   As Long
  441.  
  442.     hLib = LoadLibrary(strFile)
  443.     If hLib = 0 Then Exit Function
  444.  
  445.     If register Then
  446.         fpReg = GetProcAddress(hLib, "DllRegisterServer")
  447.     Else
  448.         fpReg = GetProcAddress(hLib, "DllUnregisterServer")
  449.     End If
  450.  
  451.     If fpReg = 0 Then Exit Function
  452.  
  453.     CallStd fpReg
  454.  
  455.     RegisterServer = True
  456. End Function
  457.  
  458. Private Function AllocMemory( _
  459.     ByVal bytes As Long, _
  460.     Optional ByVal lpAddr As Long = 0, _
  461.     Optional ByVal PageFlags As VirtualAllocPageFlags = PAGE_READWRITE _
  462. ) As allocated_memory
  463.  
  464.     With AllocMemory
  465.         .address = VirtualAlloc(lpAddr, bytes, MEM_COMMIT, PageFlags)
  466.         .bytes = bytes
  467.     End With
  468. End Function
  469.  
  470. Private Function FreeMemory( _
  471.     udtMem As allocated_memory _
  472. ) As Boolean
  473.  
  474.     VirtualFree udtMem.address, udtMem.bytes, MEM_DECOMMIT
  475.  
  476.     udtMem.address = 0
  477.     udtMem.bytes = 0
  478. End Function
  479.  
  480. Private Function CallStd( _
  481.     ByVal fnc As Long, _
  482.     ParamArray Params() As Variant _
  483. ) As Long
  484.  
  485.     Dim udtMem              As allocated_memory
  486.     Dim pASM                As Long
  487.     Dim i                   As Integer
  488.  
  489.     udtMem = AllocMemory(&HEC00&, , PAGE_EXECUTE_READWRITE)
  490.     If udtMem.address = 0 Then Exit Function
  491.     pASM = udtMem.address
  492.  
  493.     AddByte pASM, &H58                  ' POP EAX
  494.     AddByte pASM, &H59                  ' POP ECX
  495.     AddByte pASM, &H59                  ' POP ECX
  496.     AddByte pASM, &H59                  ' POP ECX
  497.     AddByte pASM, &H59                  ' POP ECX
  498.     AddByte pASM, &H50                  ' PUSH EAX
  499.  
  500.     If UBound(Params) = 0 Then
  501.         If IsArray(Params(0)) Then
  502.             For i = UBound(Params(0)) To 0 Step -1
  503.                 AddPush pASM, CLng(Params(0)(i))    ' PUSH dword
  504.             Next
  505.         Else
  506.             For i = UBound(Params) To 0 Step -1
  507.                 AddPush pASM, CLng(Params(i))       ' PUSH dword
  508.             Next
  509.         End If
  510.     Else
  511.         For i = UBound(Params) To 0 Step -1
  512.             AddPush pASM, CLng(Params(i))           ' PUSH dword
  513.         Next
  514.     End If
  515.  
  516.     AddCall pASM, fnc                   ' CALL rel addr
  517.     AddByte pASM, &HC3                  ' RET
  518.  
  519.     CallStd = CallWindowProc(udtMem.address, _
  520.                              0, 0, 0, 0)
  521.  
  522.     FreeMemory udtMem
  523. End Function
  524.  
  525. Private Sub AddPush( _
  526.     pASM As Long, _
  527.     lng As Long _
  528. )
  529.  
  530.     AddByte pASM, &H68
  531.     AddLong pASM, lng
  532. End Sub
  533.  
  534. Private Sub AddCall( _
  535.     pASM As Long, _
  536.     addr As Long _
  537. )
  538.  
  539.     AddByte pASM, &HE8
  540.     AddLong pASM, addr - pASM - 4
  541. End Sub
  542.  
  543. Private Sub AddLong( _
  544.     pASM As Long, _
  545.     lng As Long _
  546. )
  547.  
  548.     CpyMem ByVal pASM, lng, 4
  549.     pASM = pASM + 4
  550. End Sub
  551.  
  552. Private Sub AddByte( _
  553.     pASM As Long, _
  554.     Bt As Byte _
  555. )
  556.  
  557.     CpyMem ByVal pASM, Bt, 1
  558.     pASM = pASM + 1
  559. End Sub
  560.