Subversion Repositories spacemission

Rev

Rev 21 | Details | Compare with Previous | Last modification | View Log | RSS feed

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