Subversion Repositories spacemission

Rev

Rev 4 | Rev 16 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 daniel-mar 1
unit DXPlay;
2
 
3
interface
4
 
5
{$INCLUDE DelphiXcfg.inc}
6
 
10 daniel-mar 7
{$IFNDEF UseDirectPlay} // Daniel Marschall 12.04.2024 Added to avoid Windows showing "This app requires DirectPlay"
8
{$MESSAGE ERROR 'If you want to use DXPlay.pas, please enable the IFDEF UseDirectPlay in DelphiXcfg.inc'}
9
{$ENDIF}
10
 
1 daniel-mar 11
uses
4 daniel-mar 12
  Windows, SysUtils, Classes, Forms, DXClass, ActiveX, DXETable,  
13
{$IfDef StandardDX}
14
  DirectDraw,
15
// Delphi 2010 cannot be use DirectPlay8 because structure was not rewriten
16
//  {$IfDef DX9}
17
//  DirectPlay8, DX7toDX8;
18
//  {$Else}
19
  DirectPlay; //old wersion, current in directory
20
//  {$EndIf}
21
{$Else}
22
  DirectX;
23
{$EndIf}
24
 
1 daniel-mar 25
type
4 daniel-mar 26
  {$IfDef DX9}
27
  TDPID = DWORD;
28
  {$EndIf}
1 daniel-mar 29
 
30
  {  TDXPlayPlayer  }
31
 
32
  TDXPlayPlayer = class(TCollectionItem)
33
  private
34
    FData: Pointer;
35
    FID: TDPID;
36
    FName: string;
37
    FRemotePlayer: Boolean;
38
  public
39
    property Data: Pointer read FData write FData;
40
    property ID: TDPID read FID;
41
    property Name: string read FName;
42
    property RemotePlayer: Boolean read FRemotePlayer;
43
  end;
44
 
45
  {  TDXPlayPlayers  }
46
 
47
  TDXPlayPlayers = class(TCollection)
48
  private
49
    function GetPlayer(Index: Integer): TDXPlayPlayer;
50
  public
51
    constructor Create;
52
    function Find(ID: TDPID): TDXPlayPlayer;
53
    function IndexOf(ID: TDPID): Integer;
54
    property Players[Index: Integer]: TDXPlayPlayer read GetPlayer; default;
55
  end;
56
 
57
  {  TDXPlayModemSetting  }
58
 
59
  TDXPlayModemSetting = class(TPersistent)
60
  private
61
    FEnabled: Boolean;
62
    FPhoneNumber: string;
63
    FModemName: string;
64
    FModemNames: TStrings;
65
    function GetModemNames: TStrings;
66
  public
67
    destructor Destroy; override;
68
    procedure Assign(Source: TPersistent); override;
69
    property ModemName: string read FModemName write FModemName;
70
    property ModemNames: TStrings read GetModemNames;
71
  published
72
    property Enabled: Boolean read FEnabled write FEnabled;
73
    property PhoneNumber: string read FPhoneNumber write FPhoneNumber;
74
  end;
75
 
76
  {  TDXPlayTCPIPSetting  }
77
 
78
  TDXPlayTCPIPSetting = class(TPersistent)
79
  private
80
    FEnabled: Boolean;
81
    FHostName: string;
82
    FPort: Word;
83
  public
84
    procedure Assign(Source: TPersistent); override;
85
  published
86
    property Enabled: Boolean read FEnabled write FEnabled;
87
    property HostName: string read FHostName write FHostName;
88
    property Port: Word read FPort write FPort;
89
  end;
90
 
91
  {  EDXPlayError  }
92
 
93
  EDXPlayError = class(Exception);
94
 
95
  {  TCustomDXPlay  }
96
 
97
  TDXPlayEvent = procedure(Sender: TObject; Player: TDXPlayPlayer) of object;
98
 
99
  TDXPlayMessageEvent = procedure(Sender: TObject; From: TDXPlayPlayer;
100
    Data: Pointer; DataSize: Integer) of object;
101
 
102
  TDXPlaySendCompleteResult = (crOk, crAbort, crGeneric);
103
 
104
  TDXPlaySendCompleteEvent = procedure(Sender: TObject; MessageID: DWORD;
105
    Result: TDXPlaySendCompleteResult; SendTime: Integer) of object;
106
 
107
  TCustomDXPlay = class(TComponent)
108
  private
4 daniel-mar 109
    FDPlay: //{$IfDef DX7}
110
      IDirectPlay4A;//{$Else}IDirectPlay8Address{$EndIf};
1 daniel-mar 111
    FGUID: string;
112
    FIsHost: Boolean;
113
    FLocalPlayer: TDXPlayPlayer;
114
    FMaxPlayers: Integer;
115
    FPlayers: TDXPlayPlayers;
116
    FCalledDoOpen: Boolean;
117
    FOnAddPlayer: TDXPlayEvent;
118
    FOnClose: TNotifyEvent;
119
    FOnDeletePlayer: TDXPlayEvent;
120
    FOnMessage: TDXPlayMessageEvent;
121
    FOnOpen: TNotifyEvent;
122
    FOnSendComplete: TDXPlaySendCompleteEvent;
123
    FOnSessionLost: TNotifyEvent;
124
    FOpened: Boolean;
125
    FRecvEvent: array[0..1] of THandle;
126
    FRecvThread: TThread;
127
    FInThread: Boolean;
128
    FProviderName: string;
129
    FProviders: TStrings;
130
    FSessionName: string;
131
    FSessions: TStrings;
132
    FReadSessioned: Boolean;
133
    FModemSetting: TDXPlayModemSetting;
134
    FTCPIPSetting: TDXPlayTCPIPSetting;
135
    FAsync: Boolean;
136
    FAsyncSupported: Boolean;
137
    procedure ChangeDPlay;
4 daniel-mar 138
    procedure CreateDPlayWithoutDialog(out DPlay:
139
     //{$IfDef DX7}
140
     IDirectPlay4A;
141
     //{$Else}IDirectPlay8Address{$EndIf};
142
      const ProviderName: string);
1 daniel-mar 143
    function OpenDPlayWithLobby(out Name: string): Boolean;
144
    function OpenDPlayWithoutLobby(out Name: string): Boolean;
145
    function OpenDPlayWithoutLobby2(const NewSession: Boolean; const ProviderName, SessionName, PlayerName: string): Boolean;
146
    procedure Open_(NameS: string);
147
    procedure ReceiveMessage;
148
    function GetProviders: TStrings;
149
    function GetSessionsPty: TStrings;
150
    procedure ClearSessionList;
151
    procedure SetGUID(const Value: string);
152
    procedure SetModemSetting(Value: TDXPlayModemSetting);
153
    procedure SetProviderName(const Value: string);
154
    procedure SetTCPIPSetting(Value: TDXPlayTCPIPSetting);
155
  protected
156
    procedure DoAddPlayer(Player: TDXPlayPlayer); virtual;
157
    procedure DoClose; virtual;
158
    procedure DoDeletePlayer(Player: TDXPlayPlayer); virtual;
159
    procedure DoMessage(From: TDXPlayPlayer; Data: Pointer; DataSize: Integer); virtual;
160
    procedure DoOpen; virtual;
161
    procedure DoSessionLost; virtual;
162
    procedure DoSendComplete(MessageID: DWORD; Result: TDXPlaySendCompleteResult;
163
      SendTime: Integer); virtual;
164
  public
165
    constructor Create(AOwner: TComponent); override;
166
    destructor Destroy; override;
167
    procedure Close;
168
    procedure Open;
169
    procedure Open2(NewSession: Boolean; const SessionName, PlayerName: string);
170
    function GetProviderNameFromGUID(const ProviderGUID: TGUID): string;
171
    procedure GetSessions;
172
    procedure SendMessage(ToID: TDPID; Data: Pointer; DataSize: Integer);
173
    function SendMessageEx(ToID: TDPID; Data: Pointer; DataSize: Integer;
174
      dwFlags: DWORD): DWORD;
175
    property GUID: string read FGUID write SetGUID;
176
    property IsHost: Boolean read FIsHost;
177
    property LocalPlayer: TDXPlayPlayer read FLocalPlayer;
178
    property MaxPlayers: Integer read FMaxPlayers write FMaxPlayers;
179
    property OnAddPlayer: TDXPlayEvent read FOnAddPlayer write FOnAddPlayer;
180
    property OnClose: TNotifyEvent read FOnClose write FOnClose;
181
    property OnDeletePlayer: TDXPlayEvent read FOnDeletePlayer write FOnDeletePlayer;
182
    property OnMessage: TDXPlayMessageEvent read FOnMessage write FOnMessage;
183
    property OnOpen: TNotifyEvent read FOnOpen write FOnOpen;
184
    property OnSendComplete: TDXPlaySendCompleteEvent read FOnSendComplete write FOnSendComplete;
185
    property OnSessionLost: TNotifyEvent read FOnSessionLost write FOnSessionLost;
186
    property Opened: Boolean read FOpened;
187
    property Players: TDXPlayPlayers read FPlayers;
188
    property ProviderName: string read FProviderName write SetProviderName;
189
    property Providers: TStrings read GetProviders;
190
    property SessionName: string read FSessionName;
191
    property Sessions: TStrings read GetSessionsPty;
192
    property ModemSetting: TDXPlayModemSetting read FModemSetting write SetModemSetting;
193
    property TCPIPSetting: TDXPlayTCPIPSetting read FTCPIPSetting write SetTCPIPSetting;
194
    property Async: Boolean read FAsync write FAsync;
195
    property AsyncSupported: Boolean read FAsyncSupported;
196
  end;
197
 
198
  TDXPlay = class(TCustomDXPlay)
199
  published
200
    property Async;
201
    property GUID;
202
    property MaxPlayers;
203
    property ModemSetting;
204
    property TCPIPSetting;
205
    property OnAddPlayer;
206
    property OnClose;
207
    property OnDeletePlayer;
208
    property OnMessage;
209
    property OnOpen;
210
    property OnSendComplete;
211
    property OnSessionLost;
212
  end;
213
 
214
function DXPlayMessageType(P: Pointer): DWORD;
215
 
216
function DXPlayStringToGUID(const S: string): TGUID;
4 daniel-mar 217
function DXDirectPlayCreate(const lpGUID: TGUID; out lplpDP:
218
  //{$IfDef DX7}
219
  IDirectPlay;
220
  //{$Else}IDirectPlay8Server{$EndIf};
1 daniel-mar 221
  pUnk: IUnknown): HRESULT;
222
 
223
implementation
224
 
225
uses DXPlayFm, DXConsts;
226
 
227
function DXPlayMessageType(P: Pointer): DWORD;
228
begin
229
  Result := PDPMSG_GENERIC(P)^.dwType;
230
end;
231
 
232
function DXPlayStringToGUID(const S: string): TGUID;
233
var
234
  ErrorCode: Integer;
235
begin
236
  ErrorCode := CLSIDFromString(PWideChar(WideString(S)), Result);
237
  if ErrorCode<0 then
238
    raise EDXPlayError.Create(WindowsErrorMsg(ErrorCode));
239
end;
240
 
241
function GUIDToString(const ClassID: TGUID): string;
242
var
243
  ErrorCode: Integer;
244
  P: PWideChar;
245
begin
246
  ErrorCode := StringFromCLSID(ClassID, P);
247
  if ErrorCode<0 then
248
    raise EDXPlayError.Create(WindowsErrorMsg(ErrorCode));
249
  Result := P;
250
  CoTaskMemFree(P);
251
end;
252
 
4 daniel-mar 253
function DXDirectPlayCreate(const lpGUID: TGUID; out lplpDP:
254
  //{$IfDef DX7}
255
  IDirectPlay;
256
  //{$Else}IDirectPlay8Server{$EndIf};
1 daniel-mar 257
  pUnk: IUnknown): HRESULT;
258
type
259
  TDirectPlayCreate= function(const lpGUID: TGUID; out lplpDP: IDirectPlay; pUnk: IUnknown): HRESULT; stdcall;
260
begin
261
  Result := TDirectPlayCreate(DXLoadLibrary('DPlayX.dll', 'DirectPlayCreate'))
262
    (lpGUID, lplpDP, pUnk);
263
end;
4 daniel-mar 264
{$IFDEF UNICODE}
265
function DXDirectPlayEnumerate(lpEnumDPCallback: TDPEnumDPCallbackW; lpContext: Pointer): HRESULT;
266
type
267
  TDirectPlayEnumerateW= function(lpEnumDPCallback: TDPEnumDPCallbackW; lpContext: Pointer): HRESULT; stdcall;
268
begin
269
  Result := TDirectPlayEnumerateW(DXLoadLibrary('DPlayX.dll', 'DirectPlayEnumerateW'))
270
    (lpEnumDPCallback, lpContext);
271
end;
1 daniel-mar 272
 
4 daniel-mar 273
function DXDirectPlayLobbyCreate(const lpguidSP: TGUID; out lplpDPL: IDirectPlayLobbyW;
274
  lpUnk: IUnknown; lpData: Pointer; dwDataSize: DWORD): HRESULT;
1 daniel-mar 275
type
4 daniel-mar 276
  TDirectPlayLobbyCreateW = function(const lpguidSP: TGUID; out lplpDPL: IDirectPlayLobbyW;
277
    lpUnk: IUnknown; lpData: Pointer; dwDataSize: DWORD): HRESULT; stdcall;
278
begin
279
  Result := TDirectPlayLobbyCreateW(DXLoadLibrary('DPlayX.dll', 'DirectPlayLobbyCreateW'))
280
    (lpguidSP, lplpDPL, lpUnk, lpData, dwDataSize);
281
end;
282
{$ELSE}
283
function DXDirectPlayEnumerate(lpEnumDPCallback: TDPEnumDPCallbackA; lpContext: Pointer): HRESULT;
284
type
1 daniel-mar 285
  TDirectPlayEnumerateA= function(lpEnumDPCallback: TDPEnumDPCallbackA; lpContext: Pointer): HRESULT; stdcall;
286
begin
287
  Result := TDirectPlayEnumerateA(DXLoadLibrary('DPlayX.dll', 'DirectPlayEnumerateA'))
288
    (lpEnumDPCallback, lpContext);
289
end;
290
 
4 daniel-mar 291
function DXDirectPlayLobbyCreate(const lpguidSP: TGUID; out lplpDPL: IDirectPlayLobbyA;
1 daniel-mar 292
  lpUnk: IUnknown; lpData: Pointer; dwDataSize: DWORD): HRESULT;
293
type
294
  TDirectPlayLobbyCreateA = function(const lpguidSP: TGUID; out lplpDPL: IDirectPlayLobbyA;
295
    lpUnk: IUnknown; lpData: Pointer; dwDataSize: DWORD): HRESULT; stdcall;
296
begin
297
  Result := TDirectPlayLobbyCreateA(DXLoadLibrary('DPlayX.dll', 'DirectPlayLobbyCreateA'))
298
    (lpguidSP, lplpDPL, lpUnk, lpData, dwDataSize);
299
end;
4 daniel-mar 300
{$ENDIF}
1 daniel-mar 301
{  TDXPlayPlayers  }
302
 
303
constructor TDXPlayPlayers.Create;
304
begin
305
  inherited Create(TDXPlayPlayer);
306
end;
307
 
308
function TDXPlayPlayers.Find(ID: TDPID): TDXPlayPlayer;
309
var
310
  i: Integer;
311
begin
312
  i := IndexOf(ID);
313
  if i=-1 then
314
    raise EDXPlayError.Create(SDXPlayPlayerNotFound);
315
  Result := Players[i];
316
end;
317
 
318
function TDXPlayPlayers.IndexOf(ID: TDPID): Integer;
319
var
320
  i: Integer;
321
begin
322
  for i:=0 to Count-1 do
323
    if Players[i].FID=ID then
324
    begin
325
      Result := i;
326
      Exit;
327
    end;
328
  Result := -1;
329
end;
330
 
331
function TDXPlayPlayers.GetPlayer(Index: Integer): TDXPlayPlayer;
332
begin
333
  Result := TDXPlayPlayer(Items[Index]);
334
end;
335
 
336
{  TDXPlayModemSetting  }
337
 
338
destructor TDXPlayModemSetting.Destroy;
339
begin
340
  FModemNames.Free;
341
  inherited Destroy;
342
end;
343
 
344
procedure TDXPlayModemSetting.Assign(Source: TPersistent);
345
begin
346
  if Source is TDXPlayModemSetting then
347
  begin
348
    FEnabled := TDXPlayModemSetting(Source).FEnabled;
349
    FPhoneNumber := TDXPlayModemSetting(Source).FPhoneNumber;
350
    FModemName := TDXPlayModemSetting(Source).FModemName;
351
  end else
352
    inherited Assign(Source);
353
end;
354
 
355
function TDXPlayModemSetting.GetModemNames: TStrings;
356
 
357
  function EnumModemAddress(const guidDataType: TGUID;
358
    dwDataSize: DWORD; lpData: Pointer; lpContext: Pointer): BOOL; stdcall;
359
  begin
360
    if CompareMem(@guidDataType, @DPAID_Modem, SizeOf(TGUID)) then
361
      TStrings(lpContext).Add( PChar(lpData));
362
    Result := True;
363
  end;
364
 
365
var
4 daniel-mar 366
  {$IFDEF UNICODE}
367
  Lobby1: IDirectPlayLobbyW;
368
  Lobby: IDirectPlayLobby2W;
369
  DPlay: IDirectPlay4W;
370
  {$ELSE}
1 daniel-mar 371
  Lobby1: IDirectPlayLobbyA;
372
  Lobby: IDirectPlayLobby2A;
4 daniel-mar 373
  DPlay: IDirectPlay4A;
374
  {$ENDIF}
1 daniel-mar 375
  DPlay1: IDirectPlay;
376
  lpAddress: Pointer;
377
  dwAddressSize: DWORD;
378
begin
379
  if FModemNames=nil then
380
  begin
381
    FModemNames := TStringList.Create;
382
    try
4 daniel-mar 383
      if DXDirectPlayLobbyCreate(PGUID(nil)^, Lobby1, nil, nil, 0)<>0 then
1 daniel-mar 384
        raise EDXPlayError.CreateFmt(SCannotInitialized, [SDirectPlay]);
4 daniel-mar 385
      Lobby := Lobby1 as {$IFDEF UNICODE}IDirectPlayLobby2W{$ELSE}IDirectPlayLobby2A{$ENDIF};
1 daniel-mar 386
 
387
      if DXDirectPlayCreate(DPSPGUID_MODEM, DPlay1, nil)<>0 then
388
        raise EDXPlayError.CreateFmt(SCannotInitialized, [SDirectPlay]);
4 daniel-mar 389
      DPlay := DPlay1 as {$IFDEF UNICODE}IDirectPlay4W{$ELSE}IDirectPlay4A{$ENDIF};
1 daniel-mar 390
 
391
      {  get size of player address for all players  }
4 daniel-mar 392
      if DPlay.GetPlayerAddress(DPID_ALLPLAYERS, nil, dwAddressSize)<>DPERR_BUFFERTOOSMALL then
1 daniel-mar 393
        raise EDXPlayError.Create(SDXPlayModemListCannotBeAcquired);
394
 
395
      GetMem(lpAddress, dwAddressSize);
396
      try
397
        FillChar(lpAddress^, dwAddressSize, 0);
398
 
399
        {  get the address  }
4 daniel-mar 400
        if DPlay.GetPlayerAddress(DPID_ALLPLAYERS, lpAddress, dwAddressSize)<>0 then
1 daniel-mar 401
          raise EDXPlayError.Create(SDXPlayModemListCannotBeAcquired);
402
 
403
        {  get modem strings from address and put them in the combo box  }
404
        if Lobby.EnumAddress(@EnumModemAddress, lpAddress^, dwAddressSize, FModemNames)<>0 then
405
          raise EDXPlayError.Create(SDXPlayModemListCannotBeAcquired);
406
      finally
407
        FreeMem(lpAddress);
408
      end;
409
    except
410
      FModemNames.Free; FModemNames := nil;
411
      raise;
412
    end;
413
  end;
414
 
415
  Result := FModemNames;
416
end;
417
 
418
{  TDXPlayTCPIPSetting  }
419
 
420
procedure TDXPlayTCPIPSetting.Assign(Source: TPersistent);
421
begin
422
  if Source is TDXPlayTCPIPSetting then
423
  begin
424
    FEnabled := TDXPlayTCPIPSetting(Source).FEnabled;
425
    FHostName := TDXPlayTCPIPSetting(Source).FHostName;
426
  end else
427
    inherited Assign(Source);
428
end;
429
 
430
{  TCustomDXPlay  }
431
 
432
constructor TCustomDXPlay.Create(AOwner: TComponent);
433
begin
434
  inherited Create(AOwner);
435
  FPlayers := TDXPlayPlayers.Create;
436
  FModemSetting := TDXPlayModemSetting.Create;
437
  FTCPIPSetting := TDXPlayTCPIPSetting.Create;
438
  FSessions := TStringList.Create;
439
 
440
  FGUID := GUIDToString(GUID_NULL);
441
  FMaxPlayers := 0;
442
end;
443
 
444
destructor TCustomDXPlay.Destroy;
445
var
446
  i: Integer;
447
begin
448
  Close;
449
 
450
  FPlayers.Free;
451
 
452
  if FProviders<>nil then
453
  begin
454
    for i:=0 to FProviders.Count-1 do
455
      Dispose(PGUID(FProviders.Objects[i]));
456
  end;
457
  FProviders.Free;
458
  FModemSetting.Free;
459
  FTCPIPSetting.Free;
460
  ClearSessionList;
461
  FSessions.Free;
462
  inherited Destroy;
463
end;
464
 
465
type
466
  TDXPlayRecvThread = class(TThread)
467
  private
468
    FDXPlay: TCustomDXPlay;
469
    constructor Create(DXPlay: TCustomDXPlay);
470
    destructor Destroy; override;
471
    procedure Execute; override;
472
  end;
473
 
474
constructor TDXPlayRecvThread.Create(DXPlay: TCustomDXPlay);
475
begin
476
  FDXPlay := DXPlay;
477
 
478
  FDXPlay.FRecvEvent[1] := CreateEvent(nil, False, False, nil);
479
 
480
  FreeOnTerminate := True;
481
  inherited Create(True);
482
end;
483
 
484
destructor TDXPlayRecvThread.Destroy;
485
begin
486
  FreeOnTerminate := False;
487
  SetEvent(FDXPlay.FRecvEvent[1]);
488
 
489
  inherited Destroy;
490
 
491
  CloseHandle(FDXPlay.FRecvEvent[1]);
492
 
493
  FDXPlay.FRecvThread := nil;
494
  FDXPlay.Close;
495
end;
496
 
497
procedure TDXPlayRecvThread.Execute;
498
begin
499
  while WaitForMultipleObjects(2, @FDXPlay.FRecvEvent, False, INFINITE)=WAIT_OBJECT_0 do
500
  begin
501
    Synchronize(FDXPlay.ReceiveMessage);
502
  end;
503
end;
504
 
505
procedure TCustomDXPlay.ReceiveMessage;
506
var
507
  idFrom, idTo: DWORD;
508
  hr: HRESULT;
509
  lpvMsgBuffer: Pointer;
510
  dwMsgBufferSize: DWORD;
511
  Msg_CreatePlayerOrGroup: PDPMSG_CREATEPLAYERORGROUP;
512
  Msg_DeletePlayerOrGroup: PDPMSG_DESTROYPLAYERORGROUP;
513
  Msg_SendComplete: PDPMsg_SendComplete;
514
  SendCompleteResult: TDXPlaySendCompleteResult;
515
  Player: TDXPlayPlayer;
516
  i: Integer;
517
begin
518
  FInThread := True;
519
  try
520
    try
521
      lpvMsgBuffer := nil;
522
      dwMsgBufferSize := 0;
523
 
524
      try
525
        repeat
4 daniel-mar 526
          hr := FDPlay.Receive(idFrom, idTo, DPRECEIVE_ALL, lpvMsgBuffer, dwMsgBufferSize);
1 daniel-mar 527
 
528
          if hr=DPERR_BUFFERTOOSMALL then
529
          begin
530
            ReAllocMem(lpvMsgBuffer, dwMsgBufferSize);
4 daniel-mar 531
            hr := FDPlay.Receive(idFrom, idTo, DPRECEIVE_ALL, lpvMsgBuffer, dwMsgBufferSize);
1 daniel-mar 532
          end;
533
 
534
          if (hr=0) and (dwMsgBufferSize>=SizeOf(TDPMSG_GENERIC)) then
535
          begin
536
            if idFrom=DPID_SYSMSG then
537
            begin
538
              {  System message  }
539
              case PDPMSG_GENERIC(lpvMsgBuffer)^.dwType of
540
                DPSYS_CREATEPLAYERORGROUP:
541
                  begin
542
                    {  New player  }
543
                    Msg_CreatePlayerOrGroup := lpvMsgBuffer;
544
 
545
                    if Msg_CreatePlayerOrGroup.DPID<>FLocalPlayer.FID then
546
                    begin
547
                      Player := TDXPlayPlayer.Create(Players);
548
                      Player.FID := Msg_CreatePlayerOrGroup.DPID;
549
                      Player.FRemotePlayer := True;
550
 
551
                      with Msg_CreatePlayerOrGroup.dpnName do
552
                      begin
4 daniel-mar 553
                        {$IFDEF UNICODE}
554
                        if lpszShortNameW<>nil then
555
                          Player.FName := lpszShortNameW;
556
                        {$ELSE}
1 daniel-mar 557
                        if lpszShortNameA<>nil then
558
                          Player.FName := lpszShortNameA;
4 daniel-mar 559
                        {$ENDIF}
1 daniel-mar 560
                      end;
561
 
562
                      DoAddPlayer(Player);
563
                    end;
564
                  end;
565
                DPSYS_DESTROYPLAYERORGROUP:
566
                  begin
567
                    {  Player deletion  }
568
                    Msg_DeletePlayerOrGroup := lpvMsgBuffer;
569
 
570
                    if Msg_DeletePlayerOrGroup.DPID<>FLocalPlayer.FID then
571
                    begin
572
                      i := Players.IndexOf(Msg_DeletePlayerOrGroup.DPID);
573
                      if i<>-1 then
4 daniel-mar 574
                      begin
1 daniel-mar 575
                        Player := Players[i];
576
                        DoDeletePlayer(Player);
577
                        Player.Free;
578
                      end;
579
                    end;
580
                  end;
581
                DPSYS_SESSIONLOST:
582
                  begin
583
                    {  The session was lost.  }
584
                    DoSessionLost;
585
                    Close;
586
                  end;
587
                DPSYS_HOST:
588
                  begin
589
                    {  Here became a host.  }
590
                    FIsHost := True;
591
                  end;
592
                DPSYS_SENDCOMPLETE:
593
                   begin
594
                     { Send complete  }
595
                     Msg_SendComplete := lpvMsgBuffer;
596
                     if Msg_SendComplete.idFrom=FLocalPlayer.FID then
597
                     begin
598
                       case Msg_SendComplete.hr of
599
                         DP_OK        : SendCompleteResult := crOk;
600
                         DPERR_ABORTED: SendCompleteResult := crAbort;
601
                         else           SendCompleteResult := crGeneric;
602
                       end;
603
 
604
                       DoSendComplete(Msg_SendComplete^.dwMsgID, SendCompleteResult, Msg_SendComplete^.dwSendTime);
605
                     end;
606
                   end;
607
              end;
608
            end else
609
            begin
610
              {  Application definition message  }
611
              DoMessage(Players.Find(idFrom), lpvMsgBuffer, dwMsgBufferSize);
612
            end;
613
          end;
614
        until hr<>0;
615
      finally
616
        FreeMem(lpvMsgBuffer);
617
      end;
618
    except
619
      on E: Exception do
620
        Application.HandleException(E);
621
    end;
622
  finally
623
    FInThread := False;
624
  end;
625
end;
626
 
627
procedure TCustomDXPlay.DoAddPlayer(Player: TDXPlayPlayer);
628
begin
629
  if Assigned(FOnAddPlayer) then FOnAddPlayer(Self, Player)
630
end;
631
 
632
procedure TCustomDXPlay.DoClose;
633
begin
634
  if Assigned(FOnClose) then FOnClose(Self);
635
end;
636
 
637
procedure TCustomDXPlay.DoDeletePlayer(Player: TDXPlayPlayer);
638
begin
639
  if Assigned(FOnDeletePlayer) then FOnDeletePlayer(Self, Player)
640
end;
641
 
642
procedure TCustomDXPlay.DoMessage(From: TDXPlayPlayer; Data: Pointer; DataSize: Integer);
643
begin
644
  if Assigned(FOnMessage) then FOnMessage(Self, From, Data, DataSize);
645
end;
646
 
647
procedure TCustomDXPlay.DoOpen;
648
begin
649
  if Assigned(FOnOpen) then FOnOpen(Self);
650
end;
651
 
652
procedure TCustomDXPlay.DoSessionLost;
653
begin
654
  if Assigned(FOnSessionLost) then FOnSessionLost(Self);
655
end;
656
 
657
procedure TCustomDXPlay.DoSendComplete(MessageID: DWORD; Result: TDXPlaySendCompleteResult;
658
  SendTime: Integer);
659
begin
660
  if Assigned(FOnSendComplete) then FOnSendComplete(Self, MessageID, Result, SendTime);
661
end;
662
 
663
function TCustomDXPlay.GetProviders: TStrings;
664
 
4 daniel-mar 665
  function EnumProviderCallback(const lpguidSP: TGUID; lpSPName: {$IFDEF UNICODE}LPCTSTR{$ELSE}LPSTR{$ENDIF};
1 daniel-mar 666
      dwMajorVersion: DWORD; dwMinorVersion: DWORD; lpContext: Pointer):
667
      BOOL; stdcall;
668
  var
669
    GUID: PGUID;
670
  begin
671
    GUID := New(PGUID);
672
    Move(lpguidSP, GUID^, SizeOf(TGUID));
673
    TStrings(lpContext).AddObject(lpSPName, TObject(GUID));
674
    Result := True;
675
  end;
676
 
677
begin
678
  if FProviders=nil then
679
  begin
680
    FProviders := TStringList.Create;
681
    try
4 daniel-mar 682
      DXDirectPlayEnumerate(@EnumProviderCallback, FProviders);
1 daniel-mar 683
    except
684
      FProviders.Free; FProviders := nil;
685
      raise;
686
    end;
687
  end;
688
 
689
  Result := FProviders;
690
end;
691
 
692
procedure TCustomDXPlay.GetSessions;
693
 
694
  function EnumSessionsCallback(const lpThisSD: TDPSessionDesc2;
695
    var lpdwTimeOut: DWORD; dwFlags: DWORD; lpContext: Pointer): BOOL; stdcall;
696
  var
697
    Guid: PGUID;
698
  begin
699
    if dwFlags and DPESC_TIMEDOUT<>0 then
700
    begin
701
      Result := False;
702
      Exit;
703
    end;
704
 
705
    Guid := New(PGUID);
706
    Move(lpThisSD.guidInstance, Guid^, SizeOf(TGUID));
4 daniel-mar 707
    {$IFDEF UNICODE}
708
    TStrings(lpContext).AddObject(lpThisSD.lpszSessionNameW, TObject(Guid));
709
    {$ELSE}
1 daniel-mar 710
    TStrings(lpContext).AddObject(lpThisSD.lpszSessionNameA, TObject(Guid));
4 daniel-mar 711
    {$ENDIF}
1 daniel-mar 712
    Result := True;
713
  end;
714
 
715
var
716
  dpDesc: TDPSessionDesc2;
717
  hr: HRESULT;
718
begin
719
  if FDPlay=nil then
720
    raise EDXPlayError.Create(SDXPlayNotConnectedNow);
721
 
722
  ClearSessionList;
723
 
724
  FillChar(dpDesc, SizeOf(dpDesc), 0);
725
  dpDesc.dwSize := SizeOf(dpDesc);
726
  dpDesc.guidApplication := DXPlayStringToGUID(FGUID);
727
 
728
  hr := FDPlay.EnumSessions(dpDesc, 0, @EnumSessionsCallback, FSessions, DPENUMSESSIONS_AVAILABLE);
729
  if hr=DPERR_USERCANCEL then Abort;
730
  if hr<>0 then
731
    raise EDXPlayError.Create(SDXPlaySessionListCannotBeAcquired);
732
 
733
  FReadSessioned := True;
734
end;
735
 
736
function TCustomDXPlay.GetSessionsPty: TStrings;
737
begin
738
  if not FReadSessioned then GetSessions;
739
  Result := FSessions;
740
end;
741
 
742
function TCustomDXPlay.GetProviderNameFromGUID(const ProviderGUID: TGUID): string;
743
var
744
  i: Integer;
745
begin
746
  for i:=0 to Providers.Count-1 do
747
    if CompareMem(PGUID(Providers.Objects[i]), @ProviderGUID, SizeOf(TGUID)) then
748
    begin
749
      Result := Providers[i];
750
      Exit;
751
    end;
752
 
753
  raise EDXPlayError.Create(SDXPlayProviderSpecifiedGUIDNotFound);
754
end;
755
 
756
procedure TCustomDXPlay.CreateDPlayWithoutDialog(out DPlay: IDirectPlay4A; const ProviderName: string);
757
var
758
  i: Integer;
759
  ProviderGUID: TGUID;
760
  addressElements: array[0..15] of TDPCompoundAddressElement;
761
  dwElementCount: Integer;
4 daniel-mar 762
  {$IFDEF UNICODE}
763
  Lobby1: IDirectPlayLobbyW;
764
  Lobby: IDirectPlayLobby2W;
765
  {$ELSE}
1 daniel-mar 766
  Lobby1: IDirectPlayLobbyA;
767
  Lobby: IDirectPlayLobby2A;
4 daniel-mar 768
  {$ENDIF}
1 daniel-mar 769
  lpAddress: Pointer;
770
  dwAddressSize: DWORD;
771
begin
772
  i := Providers.IndexOf(ProviderName);
773
  if i=-1 then
774
    raise EDXPlayError.CreateFmt(SDXPlayProviderNotFound, [ProviderName]);
775
  ProviderGUID := PGUID(Providers.Objects[i])^;
776
 
777
  {  DirectPlay address making  }
4 daniel-mar 778
  if DXDirectPlayLobbyCreate(PGUID(nil)^, Lobby1, nil, nil, 0)<>0 then
1 daniel-mar 779
    raise EDXPlayError.CreateFmt(SCannotInitialized, [SDirectPlay]);
4 daniel-mar 780
  Lobby := Lobby1 as {$IFDEF UNICODE}IDirectPlayLobby2W{$ELSE}IDirectPlayLobby2A{$ENDIF};
1 daniel-mar 781
 
782
  FillChar(addressElements, SizeOf(addressElements), 0);
783
  dwElementCount := 0;
784
 
785
  addressElements[dwElementCount].guidDataType := DPAID_ServiceProvider;
786
  addressElements[dwElementCount].dwDataSize := SizeOf(TGUID);
787
  addressElements[dwElementCount].lpData := @ProviderGUID;
788
  Inc(dwElementCount);
789
 
790
  if CompareMem(@ProviderGUID, @DPSPGUID_MODEM, SizeOf(TGUID)) and ModemSetting.Enabled then
791
  begin
792
    {  Modem  }
793
    if ModemSetting.FModemName<>'' then
794
    begin
795
      addressElements[dwElementCount].guidDataType := DPAID_Modem;
796
      addressElements[dwElementCount].dwDataSize := Length(ModemSetting.FModemName)+1;
797
      addressElements[dwElementCount].lpData := PChar(ModemSetting.FModemName);
798
      Inc(dwElementCount);
799
    end;
800
 
801
    if ModemSetting.FPhoneNumber<>'' then
802
    begin
803
      addressElements[dwElementCount].guidDataType := DPAID_Phone;
804
      addressElements[dwElementCount].dwDataSize := Length(ModemSetting.FPhoneNumber)+1;
805
      addressElements[dwElementCount].lpData := PChar(ModemSetting.FPhoneNumber);
806
      Inc(dwElementCount);
807
    end;
808
  end else
809
  if CompareMem(@ProviderGUID, @DPSPGUID_TCPIP, SizeOf(TGUID)) and TCPIPSetting.Enabled then
810
  begin
811
    {  TCP/IP  }
812
    if TCPIPSetting.FHostName<>'' then
813
    begin
814
      addressElements[dwElementCount].guidDataType := DPAID_INet;
815
      addressElements[dwElementCount].dwDataSize := Length(TCPIPSetting.FHostName)+1;
816
      addressElements[dwElementCount].lpData := PChar(TCPIPSetting.FHostName);
817
      Inc(dwElementCount);
818
    end;
819
 
820
    if TCPIPSetting.Port<>0 then
4 daniel-mar 821
    begin
1 daniel-mar 822
      addressElements[dwElementCount].guidDataType := DPAID_INetPort;
823
      addressElements[dwElementCount].dwDataSize := SizeOf(TCPIPSetting.FPort);
824
      addressElements[dwElementCount].lpData := @TCPIPSetting.FPort;
4 daniel-mar 825
      Inc(dwElementCount);
1 daniel-mar 826
    end;
827
  end;
828
 
4 daniel-mar 829
  if Lobby.CreateCompoundAddress(addressElements[0], dwElementCount, nil, dwAddressSize)<>DPERR_BUFFERTOOSMALL then
1 daniel-mar 830
    raise EDXPlayError.CreateFmt(SCannotInitialized, [SDirectPlay]);
831
 
832
  GetMem(lpAddress, dwAddressSize);
833
  try
834
    FillChar(lpAddress^, dwAddressSize, 0);
835
 
4 daniel-mar 836
    if Lobby.CreateCompoundAddress(addressElements[0], dwElementCount, lpAddress, dwAddressSize)<>0 then
1 daniel-mar 837
      raise EDXPlayError.CreateFmt(SCannotInitialized, [SDirectPlay]);
838
 
839
    {  DirectPlay initialization  }
840
    if CoCreateInstance(CLSID_DirectPlay, nil, CLSCTX_INPROC_SERVER, IID_IDirectPlay4A, DPlay)<>0 then
841
      raise EDXPlayError.CreateFmt(SCannotInitialized, [SDirectPlay]);
842
    try
843
      {  DirectPlay address initialization  }
844
      if DPlay.InitializeConnection(lpAddress, 0)<>0 then
845
        raise EDXPlayError.CreateFmt(SCannotInitialized, [SDirectPlay]);
846
    except
847
      DPlay := nil;
848
      raise;
849
    end;
850
  finally
851
    FreeMem(lpAddress);
852
  end;
853
end;
854
 
855
procedure TCustomDXPlay.ClearSessionList;
856
var
857
  i: Integer;
858
begin
859
  FReadSessioned := False;
860
  for i:=0 to FSessions.Count-1 do
861
    Dispose(PGUID(FSessions.Objects[i]));
862
  FSessions.Clear;
863
end;
864
 
865
procedure TCustomDXPlay.Open;
866
var
867
  PlayerName: string;
868
begin
869
  Close;
870
  try
871
    if not OpenDPlayWithLobby(PlayerName) then
872
    begin
873
      if not OpenDPlayWithoutLobby(PlayerName) then
874
        Abort;
875
    end;
876
 
877
    Open_(PlayerName);
878
  except
879
    Close;
880
    raise;
881
  end;
882
end;
883
 
884
procedure TCustomDXPlay.Open2(NewSession: Boolean; const SessionName, PlayerName: string);
885
begin
886
  if not OpenDPlayWithoutLobby2(NewSession, ProviderName, SessionName, PlayerName) then
887
    Abort;
888
 
889
  Open_(PlayerName);
890
end;
891
 
892
procedure TCustomDXPlay.Open_(NameS: string);
893
 
894
  function EnumPlayersCallback2(TDPID: TDPID; dwPlayerType: DWORD;
895
    const lpName: TDPName; dwFlags: DWORD; lpContext: Pointer): BOOL;
896
    stdcall;
4 daniel-mar 897
  var
1 daniel-mar 898
    Player: TDXPlayPlayer;
899
  begin
900
    Player := TDXPlayPlayer.Create(TCustomDXPlay(lpContext).Players);
901
    Player.FID := TDPID;
902
    Player.FRemotePlayer := True;
903
 
904
    with lpName do
905
    begin
4 daniel-mar 906
      {$IFDEF UNICODE}
907
      if lpszShortNameW<>nil then
908
        Player.FName := lpszShortNameW;
909
      {$ELSE}
1 daniel-mar 910
      if lpszShortNameA<>nil then
911
        Player.FName := lpszShortNameA;
4 daniel-mar 912
      {$ENDIF}
1 daniel-mar 913
    end;
914
 
915
    Result := True;
916
  end;
917
 
918
var
919
  Name2: array[0..1023] of Char;
920
  Name: TDPName;
921
begin
922
  if FOpened then Close;
923
  FOpened := True;
924
  try
925
    {  Player making  }
926
    StrLCopy(@Name2, PChar(NameS), SizeOf(Name2));
927
 
928
    Name.lpszShortNameA := @Name2;
929
    Name.lpszLongNameA := nil;
930
 
931
    FRecvEvent[0] := CreateEvent(nil, False, False, nil);
932
 
933
    FLocalPlayer := TDXPlayPlayer.Create(FPlayers);
934
    FLocalPlayer.FName := NameS;
935
 
4 daniel-mar 936
    if FDPlay.CreatePlayer(FLocalPlayer.FID, @Name, FRecvEvent[0], nil, 0, 0)<>DP_OK then
1 daniel-mar 937
      raise EDXPlayError.CreateFmt(SCannotOpened, [FSessionName]);
938
 
939
    {  Player enumeration  }
4 daniel-mar 940
    FDPlay.EnumPlayers(PGUID(nil), @EnumPlayersCallback2, Self, DPENUMPLAYERS_REMOTE);
1 daniel-mar 941
 
942
    FIsHost := FPlayers.Count=1;
943
 
944
    FCalledDoOpen := True; DoOpen;
945
    DoAddPlayer(FLocalPlayer);
946
 
947
    {  Thread start  }
948
    FRecvThread := TDXPlayRecvThread.Create(Self);
949
    FRecvThread.Resume;
950
  except
951
    Close;
952
    raise;
953
  end;
954
end;
955
 
956
procedure TCustomDXPlay.ChangeDPlay;
957
var
958
  caps: TDPCAPS;
959
begin
960
  FAsyncSupported := False;
961
  if FDPlay<>nil then
962
  begin
963
    FillChar(caps, SizeOf(caps), 0);
964
    caps.dwSize := SizeOf(caps);
965
    FDPlay.GetCaps(caps, 0);
966
 
967
    FAsyncSupported := caps.dwFlags and DPCAPS_ASYNCSUPPORTED<>0;
968
  end;
969
end;
970
 
971
function TCustomDXPlay.OpenDPlayWithLobby(out Name: string): Boolean;
972
var
973
  DPlay1: IDirectPlay2;
4 daniel-mar 974
  {$IFDEF UNICODE}
975
  Lobby: IDirectPlayLobbyW;
976
  {$ELSE}
1 daniel-mar 977
  Lobby: IDirectPlayLobbyA;
4 daniel-mar 978
  {$ENDIF}
1 daniel-mar 979
  dwSize: DWORD;
980
  ConnectionSettings: PDPLConnection;
981
begin
982
  Result := False;
983
 
4 daniel-mar 984
  if DXDirectPlayLobbyCreate(PGUID(nil)^, Lobby, nil, nil, 0)<>0 then
1 daniel-mar 985
    Exit;
986
 
4 daniel-mar 987
  if Lobby.GetConnectionSettings(0, PDPLConnection(nil), dwSize)<>DPERR_BUFFERTOOSMALL then
1 daniel-mar 988
    Exit;
989
 
990
  GetMem(ConnectionSettings, dwSize);
991
  try
4 daniel-mar 992
    if Lobby.GetConnectionSettings(0, ConnectionSettings, dwSize)<>0 then
1 daniel-mar 993
      Exit;
994
 
995
    with ConnectionSettings^.lpSessionDesc^ do
996
    begin
997
      dwFlags := DPSESSION_MIGRATEHOST or DPSESSION_KEEPALIVE or DPSESSION_DIRECTPLAYPROTOCOL;
998
      dwMaxPlayers := FMaxPlayers;
999
    end;
1000
 
1001
    if Lobby.SetConnectionSettings(0, 0, ConnectionSettings^)<>0 then
1002
      Exit;
1003
 
1004
    if Lobby.Connect(0, DPlay1, nil)<>0 then
1005
      Exit;
1006
    FDPlay := DPlay1 as IDirectPlay4A;
1007
    ChangeDPlay;
1008
 
1009
    with ConnectionSettings.lpSessionDesc^ do
1010
    begin
4 daniel-mar 1011
      {$IFDEF UNICODE}
1012
      if lpszSessionNameW<>nil then
1013
        FSessionName := lpszSessionNameW;
1014
      {$ELSE}
1 daniel-mar 1015
      if lpszSessionNameA<>nil then
1016
        FSessionName := lpszSessionNameA;
4 daniel-mar 1017
      {$ENDIF}
1 daniel-mar 1018
    end;
1019
 
1020
    with ConnectionSettings.lpPlayerName^ do
1021
    begin
4 daniel-mar 1022
      {$IFDEF UNICODE}
1023
      if lpszShortNameW<>nil then
1024
        Name := lpszShortNameW;
1025
      {$ELSE}
1 daniel-mar 1026
      if lpszShortNameA<>nil then
1027
        Name := lpszShortNameA;
4 daniel-mar 1028
      {$ENDIF}
1 daniel-mar 1029
    end;
1030
  finally
1031
    FreeMem(ConnectionSettings);
1032
  end;
1033
 
1034
  Result := True;
1035
end;
1036
 
1037
function TCustomDXPlay.OpenDPlayWithoutLobby(out Name: string): Boolean;
1038
var
1039
  Form: TDelphiXDXPlayForm;
1040
begin
1041
  Form := TDelphiXDXPlayForm.Create(Application);
1042
  try
1043
    Form.DXPlay := Self;
1044
    Form.ShowModal;
1045
 
1046
    Result := Form.Tag<>0;
1047
 
1048
    FDPlay := Form.DPlay;
1049
    ChangeDPlay;
1050
 
1051
    Name := Form.PlayerName;
1052
    FProviderName := Form.ProviderName;
1053
    FSessionName := Form.SessionName;
1054
  finally
1055
    Form.Free;
1056
  end;
1057
end;
1058
 
1059
function TCustomDXPlay.OpenDPlayWithoutLobby2(const NewSession: Boolean;
1060
  const ProviderName, SessionName, PlayerName: string): Boolean;
1061
var
1062
  dpDesc: TDPSessionDesc2;
1063
  i: Integer;
1064
  hr: HRESULT;
1065
begin
1066
  Result := False;
1067
 
1068
  if FDPlay=nil then
1069
    raise EDXPlayError.Create(SDXPlayNotConnectedNow);
1070
 
1071
  if SessionName='' then
1072
    raise EDXPlayError.Create(SDXPlaySessionNameIsNotSpecified);
1073
 
1074
  if PlayerName='' then
1075
    raise EDXPlayError.Create(SDXPlayPlayerNameIsNotSpecified);
1076
 
1077
  if NewSession then
1078
  begin
1079
    {  Session connection  }
1080
    FillChar(dpDesc, SizeOf(dpDesc), 0);
1081
    dpDesc.dwSize := SizeOf(dpDesc);
1082
    dpDesc.dwFlags := DPSESSION_MIGRATEHOST or DPSESSION_KEEPALIVE;
4 daniel-mar 1083
    {$IFDEF UNICODE}
1084
    dpDesc.lpszSessionNameW := {$IFDEF VER12UP}PChar{$ELSE}PWideChar{$ENDIF}(SessionName);
1085
    {$ELSE}
1086
    dpDesc.lpszSessionNameA := PAnsiChar(SessionName);
1087
    {$ENDIF}
1 daniel-mar 1088
    dpDesc.guidApplication := DXPlayStringToGUID(GUID);
1089
    dpDesc.dwMaxPlayers := MaxPlayers;
1090
 
1091
    hr := FDPlay.Open(dpDesc, DPOPEN_CREATE);
1092
    if hr=DPERR_USERCANCEL then Exit;
1093
    if hr<>0 then
1094
      raise EDXPlayError.CreateFmt(SDXPlaySessionCannotOpened, [FSessionName]);
1095
  end else
1096
  begin
1097
    {  Session connection  }
1098
    {  Enum session  }
1099
    i := Sessions.IndexOf(SessionName);
1100
    if i=-1 then raise EDXPlayError.CreateFmt(SDXPlaySessionNotFound, [SessionName]);
1101
 
1102
    FillChar(dpDesc, SizeOf(dpDesc), 0);
1103
    dpDesc.dwSize := SizeOf(dpDesc);
1104
    dpDesc.guidInstance := PGUID(Sessions.Objects[i])^;
1105
    dpDesc.guidApplication := DXPlayStringToGUID(GUID);
1106
 
1107
    hr := FDPlay.Open(dpDesc, DPOPEN_JOIN);
1108
    if hr=DPERR_USERCANCEL then Exit;
1109
    if hr<>0 then
1110
      raise EDXPlayError.CreateFmt(SDXPlaySessionCannotOpened, [FSessionName]);
1111
  end;
1112
 
1113
  Result := True;
1114
 
1115
  FSessionName := SessionName;
1116
end;
1117
 
1118
procedure TCustomDXPlay.Close;
1119
begin
1120
  FOpened := False;
1121
  FReadSessioned := False;
1122
 
1123
  try
1124
    if FCalledDoOpen then
1125
    begin
1126
      FCalledDoOpen := False;
1127
      DoClose;
1128
    end;
1129
  finally
1130
    if FDPlay<>nil then
1131
    begin
1132
      if FLocalPlayer<>nil then FDPlay.DestroyPlayer(FLocalPlayer.FID);
1133
      FDPlay.Close;
1134
    end;
1135
 
1136
    FProviderName := '';
1137
    FSessionName := '';
1138
    FAsyncSupported := False;
4 daniel-mar 1139
 
1 daniel-mar 1140
    ClearSessionList;
1141
 
1142
    FDPlay := nil;
1143
    ChangeDPlay;
1144
 
1145
    if FInThread then
1146
      SetEvent(FRecvEvent[1])
1147
    else
1148
      FRecvThread.Free;
4 daniel-mar 1149
 
1 daniel-mar 1150
    CloseHandle(FRecvEvent[0]); FRecvEvent[0] := 0;
1151
 
1152
    FPlayers.Clear;
1153
 
1154
    FLocalPlayer := nil;
1155
  end;
1156
end;
1157
 
1158
procedure TCustomDXPlay.SendMessage(ToID: TDPID; Data: Pointer; DataSize: Integer);
1159
begin
1160
  if not Opened then Exit;
1161
 
1162
  if DataSize<SizeOf(TDPMSG_GENERIC) then
1163
    raise EDXPlayError.Create(SDXPlayMessageIllegal);
1164
 
1165
  if ToID=FLocalPlayer.ID then
1166
  begin
1167
    {  Message to me  }
1168
    DoMessage(FLocalPlayer, Data, DataSize);
1169
  end else
1170
  if FAsync and FAsyncSupported then
4 daniel-mar 1171
    FDPlay.SendEx(FLocalPlayer.ID, ToID, DPSEND_GUARANTEED or DPSEND_ASYNC, Data, DataSize, 0, 0, nil, nil)
1 daniel-mar 1172
  else
1173
    FDPlay.Send(FLocalPlayer.ID, ToID, DPSEND_GUARANTEED, Data^, DataSize);
1174
end;
1175
 
1176
function TCustomDXPlay.SendMessageEx(ToID: TDPID; Data: Pointer; DataSize: Integer;
1177
  dwFlags: DWORD): DWORD;
1178
begin
1179
  if not Opened then Exit;
1180
 
1181
  if DataSize<SizeOf(TDPMSG_GENERIC) then
1182
    raise EDXPlayError.Create(SDXPlayMessageIllegal);
1183
 
1184
  Result := 0;
1185
  if ToID=FLocalPlayer.ID then
1186
  begin
1187
    {  自分宛のメッセ[ジ  }
1188
    DoMessage(FLocalPlayer, Data, DataSize);
1189
  end else
4 daniel-mar 1190
    FDPlay.SendEx(FLocalPlayer.ID, ToID, dwFlags, Data, DataSize,
1 daniel-mar 1191
      0, 0, nil, @Result); // 0 以外はサポ[トしないデバイスあるので使わない
1192
end;
1193
 
1194
procedure TCustomDXPlay.SetGUID(const Value: string);
1195
begin
1196
  if Value<>FGUID then
1197
  begin
1198
    if Value='' then
1199
    begin
1200
      FGUID := GUIDToString(GUID_NULL);
1201
    end else
1202
    begin
1203
      FGUID := GUIDToString(DXPlayStringToGUID(Value));
1204
    end;
1205
  end;
1206
end;
1207
 
1208
procedure TCustomDXPlay.SetModemSetting(Value: TDXPlayModemSetting);
1209
begin
1210
  FModemSetting.Assign(Value);
1211
end;
1212
 
1213
procedure TCustomDXPlay.SetProviderName(const Value: string);
1214
begin
1215
  Close;
1216
  FProviderName := Value;
1217
  if FProviderName='' then Exit;
1218
  try
1219
    CreateDPlayWithoutDialog(FDPlay, Value);
1220
  except
1221
    FProviderName := '';
1222
    raise;
1223
  end;
1224
end;
1225
 
1226
procedure TCustomDXPlay.SetTCPIPSetting(Value: TDXPlayTCPIPSetting);
1227
begin
1228
  FTCPIPSetting.Assign(Value);
1229
end;
1230
 
1231
initialization
1232
  CoInitialize(nil);
1233
finalization
1234
  CoUninitialize;
4 daniel-mar 1235
end.