1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219:
| unit MutexMIC;
interface
uses Windows, Messages, SysUtils, Classes, Forms, Dialogs;
type TReceiveEvent = procedure(SourceID : Byte;var X;Size : Word) of object; TConnectEvent = procedure(SourceID : Byte) of object; TOnMessage = procedure(var msg: tagMsg; var Handled: Boolean) of object;
TMutexMIC = class(TComponent) private MMFSize, MMFBlock : Cardinal; InstanceNumber : Byte; InstanceRunning : array[0..254] of Boolean; MainMutex : THandle; HMMF : THandle; LockMutex : THandle; PMMF : Pointer; MIC_SEND : UINT; MIC_ONOFF : UINT; FOnReceive : TReceiveEvent; FOnConnect : TConnectEvent; OldOnMessage : TOnMessage; FName : string; function MMFLock : Boolean; procedure MMFUnlock; procedure MICReceiver(var msg: tagMsg; var Handled: Boolean); protected public constructor Create(AOwner : TComponent;Name : string;MMFBlockCount, MMFBlockSize : Cardinal);reintroduce; procedure AfterConstruction;override; procedure BeforeDestruction;override; published property ID : Byte read InstanceNumber; property Name : string read FName; function IsRunning(ID : Byte) : Boolean; procedure Send(DestID : Byte;var X;Size : Word); property OnReceive : TReceiveEvent read FOnReceive write FOnReceive; property OnConnect : TConnectEvent read FOnConnect write FOnConnect; end;
implementation
constructor TMutexMIC.Create(AOwner : TComponent;Name : string;MMFBlockCount, MMFBlockSize : Cardinal); begin inherited Create(AOwner); FName:=Name; MMFBlock:=MMFBlockSize; if MMFBlock > 65536 then MMFBlock:=65536; MMFSize:=MMFBlockCount*MMFBlock; MIC_SEND:=RegisterWindowMessage(PChar('MIC_'+FName+'_SEND')); MIC_ONOFF:=RegisterWindowMessage(PChar('MIC_'+FName+'_ONOFF')); end;
procedure TMutexMIC.AfterConstruction; var a : Integer; b : Boolean; TempHandle : THandle; begin InstanceNumber:=255; for a:=0 to 254 do begin InstanceRunning[a]:=True; TempHandle:=CreateMutex(nil,True,PChar('TMutexMIC-'+FName+'-MAIN-'+InttoStr(a))); if GetLastError = 0 then begin if InstanceNumber = 255 then begin InstanceNumber:=a; MainMutex:=TempHandle; end else begin InstanceRunning[a]:=False; CloseHandle(TempHandle); end; end else CloseHandle(TempHandle); end; if MainMutex = 0 then Halt; PostMessage(HWND_BROADCAST,MIC_ONOFF,InstanceNumber,0); HMMF:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,MMFSize,PChar('TMutexMIC-'+FName+'-MMF')); b:=GetLastError <> ERROR_ALREADY_EXISTS; if HMMF = 0 then Halt; PMMF:=MapViewOfFile(HMMF,FILE_MAP_ALL_ACCESS,0,0,0); if PMMF = nil then begin CloseHandle(HMMF); Halt; end; if b then FillChar(PMMF^,MMFSize,0); OldOnMessage:=Application.OnMessage; Application.OnMessage:=MICReceiver; end;
procedure TMutexMIC.BeforeDestruction; begin PostMessage(HWND_BROADCAST,MIC_ONOFF,InstanceNumber,1); UnMapViewOfFile(PMMF); CloseHandle(HMMF); CloseHandle(MainMutex); end;
function TMutexMIC.IsRunning(ID : Byte) : Boolean; begin Result:=InstanceRunning[ID]; end;
function TMutexMIC.MMFLock : Boolean; begin Result:=True; LockMutex:=CreateMutex(nil,False,PChar('TMutexMIC-'+FName+'-LOCK')); if LockMutex = 0 then Result:=False else if WaitForSingleObject(LockMutex,1000) = WAIT_FAILED then Result:=False; end;
procedure TMutexMIC.MMFUnlock; begin ReleaseMutex(LockMutex); CloseHandle(LockMutex); end;
procedure TMutexMIC.Send(DestID : Byte;var X;Size : Word); var a, b : Integer; buf : array[0..3] of Byte; w : Word; p : ^Byte; begin if not InstanceRunning[DestID] then Exit; if Size > MMFBlock-4 then Exit; if MMFLock then begin buf[0]:=InstanceNumber; buf[1]:=DestID; buf[2]:=Hi(Size); buf[3]:=Lo(Size); b:=MMFSize div MMFBlock-1; p:=PMMF; for a:=0 to b do begin Move(p^,w,2); if w = 0 then begin Move(buf,p^,4); Inc(p,4); Move(X,p^,Size); Break; end; Inc(p,MMFBlock); end; MMFUnlock; PostMessage(HWND_BROADCAST,MIC_SEND,InstanceNumber,DestID); end; end;
procedure TMutexMIC.MICReceiver(var msg: tagMsg; var Handled: Boolean); var a, b : Integer; buf : array[0..3] of Byte; dat : array of Byte; p : ^Byte; SourceID : Byte; begin if (msg.message = MIC_SEND) and (msg.lParam = InstanceNumber) then begin if MMFLock then begin SourceID:=255; b:=MMFSize div MMFBlock-1; p:=PMMF; for a:=0 to b do begin Move(p^,buf,4); if (buf[1] = InstanceNumber) and (buf[2]*256+buf[3] > 0) then begin SourceID:=buf[0]; SetLength(dat,buf[2]*256+buf[3]); Inc(p,4); Move(p^,dat[0],Length(dat)); Dec(p,4); FillChar(buf,4,0); Move(buf,p^,4); Break; end; Inc(p,MMFBlock); end; MMFUnlock; if Assigned(FOnReceive) then FOnReceive(SourceID,dat[0],Length(dat)); end; Handled:=True; Exit; end; if msg.message = MIC_ONOFF then begin if msg.lParam = 0 then InstanceRunning[msg.wParam]:=True else InstanceRunning[msg.wParam]:=False; if Assigned(FOnConnect) then FOnConnect(msg.wparam); Handled:=True; Exit; end; if Assigned(OldOnMessage) then OldOnMessage(msg,Handled); end;
end. |