00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
#include "precomp.h"
00013
#pragma hdrstop
00014
#include "nddeagnt.h"
00015
00016
00017
#ifdef TESTING
00018
ULONG
00019
DbgPrint(
00020 PCH Format,
00021 ...
00022 );
00023
VOID
00024 DbgUserBreakPoint(
00025 VOID
00026 );
00027
00028
BOOL ValidateConvList(
00029 HCONVLIST hConvList)
00030 {
00031
PCONVLIST pcl;
00032
PCL_CONV_INFO pci;
00033
PXACT_INFO pxi;
00034
int i;
00035
BOOL fMatch;
00036
00037
if (hConvList == 0) {
00038
return(
TRUE);
00039 }
00040 pcl = (
PCONVLIST)
ValidateCHandle((HANDLE)hConvList,
00041 HTYPE_CONVERSATION_LIST,
00042 HINST_ANY);
00043
for (i = 0; i < pcl->
chwnd; i++) {
00044
00045
00046
00047
if (!
IsWindow(pcl->
ahwnd[i])) {
00048 DebugBreak();
00049 }
00050 pci = (
PCL_CONV_INFO)
GetWindowLongPtr(pcl->
ahwnd[i], GWLP_PCI);
00051
00052
00053
00054
if (pci ==
NULL) {
00055 DebugBreak();
00056 }
00057 fMatch =
FALSE;
00058
while (pci !=
NULL) {
00059
00060
00061
00062
if (pci->
hConvList != hConvList &&
00063
TypeFromHandle(pci->
ci.
hConv) !=
HTYPE_ZOMBIE_CONVERSATION) {
00064 DebugBreak();
00065 }
00066
00067
00068
00069
if (pci->
hConvList != 0 && pci->
hConvList != hConvList) {
00070 DebugBreak();
00071 }
00072
00073
00074
00075
if (pci->
hConvList == hConvList) {
00076 fMatch =
TRUE;
00077 }
00078
for (pxi = pci->
ci.
pxiOut; pxi; pxi = pxi->
next) {
00079
if ((
PCL_CONV_INFO)pxi->
pcoi != pci) {
00080 DebugBreak();
00081 }
00082 }
00083 pci = (
PCL_CONV_INFO)pci->
ci.
next;
00084 }
00085
if (!fMatch) {
00086
00087
00088
00089 DebugBreak;
00090 }
00091 }
00092
return(
TRUE);
00093 }
00094
00095
VOID ValidateAllConvLists()
00096 {
00097
ApplyFunctionToObjects(HTYPE_CONVERSATION_LIST, HINST_ANY,
00098 (
PFNHANDLEAPPLY)ValidateConvList);
00099 }
00100
00101
#else // TESTING
00102 #define ValidateConvList(h)
00103 #define ValidateAllConvLists()
00104
#endif // TESTING
00105
00106 CONVCONTEXT
TempConvContext;
00107 CONVCONTEXT
DefConvContext = {
00108
sizeof(CONVCONTEXT),
00109 0,
00110 0,
00111 CP_WINANSI,
00112 0
L,
00113 0
L,
00114 {
00115
sizeof(SECURITY_QUALITY_OF_SERVICE),
00116 SecurityImpersonation,
00117 SECURITY_STATIC_TRACKING,
00118
TRUE
00119 }
00120 };
00121
00122 typedef struct tagINIT_ENUM {
00123 HWND
hwndClient;
00124 HWND
hwndSkip;
00125 LONG
lParam;
00126 LATOM laServiceRequested;
00127 LATOM laTopic;
00128 HCONVLIST hConvList;
00129 DWORD clst;
00130 }
INIT_ENUM, *
PINIT_ENUM;
00131
00132
00133
BOOL InitiateEnumerationProc(HWND hwndTarget, PINIT_ENUM pie);
00134
VOID DisconnectConv(
PCONV_INFO pcoi);
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 HCONV
DdeConnect(
00147 DWORD idInst,
00148 HSZ hszService,
00149 HSZ hszTopic,
00150 PCONVCONTEXT pCC)
00151 {
00152
PCL_INSTANCE_INFO pcii;
00153
PCL_CONV_INFO pci;
00154 HCONV hConvRet = 0;
00155 HWND hwndTarget = 0;
00156
LATOM aNormalSvcName = 0;
00157
00158
EnterDDECrit;
00159
00160
if (!
ValidateConnectParameters((HANDLE)LongToHandle( idInst ), &pcii, &hszService, hszTopic,
00161 &aNormalSvcName, &pCC, &hwndTarget, 0)) {
00162
goto Exit;
00163 }
00164 pci =
ConnectConv(pcii,
LATOM_FROM_HSZ(hszService),
LATOM_FROM_HSZ(hszTopic),
00165 hwndTarget,
00166 (pcii->
afCmd & CBF_FAIL_SELFCONNECTIONS) ? pcii->
hwndMother : 0,
00167 pCC, 0,
CLST_SINGLE_INITIALIZING);
00168
if (pci ==
NULL) {
00169
SetLastDDEMLError(pcii, DMLERR_NO_CONV_ESTABLISHED);
00170
goto Exit;
00171 }
else {
00172 hConvRet = pci->
ci.
hConv;
00173 }
00174
00175 Exit:
00176
if (aNormalSvcName) {
00177 GlobalDeleteAtom(aNormalSvcName);
00178 }
00179
LeaveDDECrit;
00180
return (hConvRet);
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 HCONVLIST
DdeConnectList(
00196 DWORD idInst,
00197 HSZ hszService,
00198 HSZ hszTopic,
00199 HCONVLIST hConvList,
00200 PCONVCONTEXT pCC)
00201 {
00202
PCL_INSTANCE_INFO pcii;
00203
PCONV_INFO pcoi, pcoiNew, pcoiExisting, pcoiNext;
00204 HCONVLIST hConvListRet = 0;
00205 HWND hwndTarget = 0;
00206
LATOM aNormalSvcName = 0;
00207
PCONVLIST pcl =
NULL;
00208 HCONVLIST hConvListOld;
00209
int i;
00210
00211
CheckDDECritOut;
00212
00213
EnterDDECrit;
00214
00215
if (!
ValidateConnectParameters((HANDLE)LongToHandle( idInst ), &pcii, &hszService, hszTopic,
00216 &aNormalSvcName, &pCC, &hwndTarget, hConvList)) {
00217
goto Exit;
00218 }
00219
00220
ValidateConvList(hConvList);
00221
00222 hConvListOld = hConvList;
00223 pcoi = (
PCONV_INFO)
ConnectConv(pcii,
00224
LATOM_FROM_HSZ(hszService),
00225
LATOM_FROM_HSZ(hszTopic),
00226 hwndTarget,
00227 (pcii->
afCmd & (CBF_FAIL_SELFCONNECTIONS | CBF_FAIL_CONNECTIONS)) ?
00228 pcii->
hwndMother : 0,
00229 pCC,
00230 hConvListOld,
00231
CLST_MULT_INITIALIZING);
00232
00233
if (pcoi ==
NULL) {
00234
00235
00236
00237
SetLastDDEMLError(pcii, DMLERR_NO_CONV_ESTABLISHED);
00238 hConvListRet = hConvListOld;
00239
goto Exit;
00240 }
00241
00242
00243
00244
00245
00246
00247
if (hConvListOld == 0) {
00248 pcl = (
PCONVLIST)
DDEMLAlloc(
sizeof(
CONVLIST));
00249
if (pcl ==
NULL) {
00250
SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR);
00251
DisconnectConv(pcoi);
00252
goto Exit;
00253 }
00254
00255
00256 hConvList = (HCONVLIST)
CreateHandle((ULONG_PTR)pcl,
00257
HTYPE_CONVERSATION_LIST,
InstFromHandle(pcii->
hInstClient));
00258
if (hConvList == 0) {
00259
DDEMLFree(pcl);
00260
SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR);
00261
DisconnectConv(pcoi);
00262
goto Exit;
00263 }
00264 }
else {
00265 pcl = (
PCONVLIST)
GetHandleData((HANDLE)hConvList);
00266 pcl =
DDEMLReAlloc(pcl,
sizeof(
CONVLIST) +
sizeof(HWND) * pcl->
chwnd);
00267
if (pcl ==
NULL) {
00268
SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR);
00269 hConvListRet = hConvListOld;
00270
DisconnectConv(pcoi);
00271
goto Exit;
00272 }
00273
SetHandleData((HANDLE)hConvList, (ULONG_PTR)pcl);
00274 }
00275
00276
ValidateConvList(hConvListOld);
00277
00278
if (hConvListOld) {
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
for (i = 0; i < pcl->
chwnd; i++) {
00291
00292
00293
00294
for (pcoiExisting = (
PCONV_INFO)
00295
GetWindowLongPtr(pcl->
ahwnd[i],
GWLP_PCI);
00296 pcoi !=
NULL && pcoiExisting !=
NULL;
00297 pcoiExisting = pcoiExisting->
next) {
00298
00299
if (!(pcoiExisting->
state & ST_CONNECTED))
00300
continue;
00301
00302
00303
00304
for (pcoiNew = pcoi; pcoiNew !=
NULL; pcoiNew = pcoiNext) {
00305
00306 pcoiNext = pcoiNew->
next;
00307
00308
00309
00310
if (!(pcoiNew->
state & ST_CONNECTED))
00311
continue;
00312
00313 UserAssert(((
PCL_CONV_INFO)pcoiExisting)->hwndReconnect);
00314 UserAssert(((
PCL_CONV_INFO)pcoiNew)->hwndReconnect);
00315
00316
if (((
PCL_CONV_INFO)pcoiExisting)->hwndReconnect ==
00317 ((
PCL_CONV_INFO)pcoiNew)->hwndReconnect &&
00318 pcoiExisting->laTopic == pcoiNew->laTopic &&
00319 pcoiExisting->laService == pcoiNew->laService) {
00320
00321
00322
00323
if (pcoiNew == pcoi) {
00324
00325
00326
00327
00328 pcoi = pcoiNext;
00329 }
00330
ValidateConvList(hConvList);
00331
ShutdownConversation(pcoiNew,
FALSE);
00332
ValidateConvList(hConvList);
00333
break;
00334 }
00335 }
00336 }
00337 }
00338
00339
for (pcoiExisting = pcoi; pcoiExisting !=
NULL; pcoiExisting = pcoiExisting->
next) {
00340
00341
00342
00343
00344
00345
if (pcoiExisting->
state & ST_CONNECTED) {
00346
goto FoundOne;
00347 }
00348 }
00349 pcoi =
NULL;
00350 FoundOne:
00351
00352
00353
00354
if (pcoi !=
NULL) {
00355 UserAssert(pcoi->hwndConv);
00356 pcl->
ahwnd[pcl->
chwnd] = pcoi->hwndConv;
00357 pcl->
chwnd++;
00358 hConvListRet = hConvList;
00359 }
else {
00360 hConvListRet = hConvListOld;
00361
if (!hConvListOld) {
00362
DestroyHandle((HANDLE)hConvList);
00363 }
00364 }
00365
00366
00367 }
else {
00368
00369 UserAssert(pcoi->
hwndConv);
00370 pcl->
ahwnd[0] = pcoi->
hwndConv;
00371 pcl->
chwnd = 1;
00372 hConvListRet = hConvList;
00373 }
00374
00375
if (pcoi !=
NULL) {
00376
00377
00378
00379 UserAssert(hConvListRet);
00380
for (pcoiNew = pcoi; pcoiNew !=
NULL; pcoiNew = pcoiNew->
next) {
00381
if (pcoiNew->
state & ST_CONNECTED) {
00382 ((
PCL_CONV_INFO)pcoiNew)->hConvList = hConvListRet;
00383 }
00384 }
00385 }
00386
00387 Exit:
00388
if (aNormalSvcName) {
00389 DeleteAtom(aNormalSvcName);
00390 }
00391
ValidateConvList(hConvListRet);
00392
LeaveDDECrit;
00393
return (hConvListRet);
00394 }
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 HCONV
DdeReconnect(
00410 HCONV hConv)
00411 {
00412
PCL_INSTANCE_INFO pcii;
00413
PCL_CONV_INFO pci, pciNew;
00414 HCONV hConvRet = 0;
00415 CONVCONTEXT cc;
00416
00417
EnterDDECrit;
00418
00419 pcii =
PciiFromHandle((HANDLE)hConv);
00420
if (pcii ==
NULL) {
00421
BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
00422
goto Exit;
00423 }
00424 pci = (
PCL_CONV_INFO)
ValidateCHandle((HANDLE)hConv,
00425
HTYPE_CLIENT_CONVERSATION,
HINST_ANY);
00426
if (pci ==
NULL) {
00427
SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
00428
goto Exit;
00429 }
00430
00431
if (pci->
ci.
state & ST_CONNECTED) {
00432
goto Exit;
00433 }
00434
00435
GetConvContext(pci->
ci.
hwndConv, (LONG *)&cc);
00436 pciNew =
ConnectConv(pcii, pci->
ci.
laService, pci->
ci.
laTopic,
00437 pci->
hwndReconnect, 0, &cc, 0,
CLST_SINGLE_INITIALIZING);
00438
if (pciNew ==
NULL) {
00439
SetLastDDEMLError(pcii, DMLERR_NO_CONV_ESTABLISHED);
00440
goto Exit;
00441 }
else {
00442 hConvRet = pciNew->
ci.
hConv;
00443
if (pci->
ci.
cLinks) {
00444
PXACT_INFO pxi;
00445
int iLink;
00446
PADVISE_LINK paLink;
00447
00448
00449
00450
00451
00452
for (paLink = pci->
ci.
aLinks, iLink = pci->
ci.
cLinks;
00453 iLink; paLink++, iLink--) {
00454
00455 pxi = (
PXACT_INFO)
DDEMLAlloc(
sizeof(
XACT_INFO));
00456
if (pxi ==
NULL) {
00457
break;
00458 }
00459 pxi->
pcoi = (
PCONV_INFO)pciNew;
00460 pxi->
gaItem =
LocalToGlobalAtom(paLink->
laItem);
00461 pxi->
wFmt = paLink->
wFmt;
00462 pxi->
wType = (WORD)((paLink->
wType >> 12) | XTYP_ADVSTART);
00463
if (
ClStartAdvise(pxi)) {
00464 pxi->
flags |=
XIF_ABANDONED;
00465 }
else {
00466 GlobalDeleteAtom(pxi->
gaItem);
00467
DDEMLFree(pxi);
00468 }
00469 }
00470 }
00471 }
00472
00473 Exit:
00474
LeaveDDECrit;
00475
return (hConvRet);
00476 }
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 BOOL ValidateConnectParameters(
00492 HANDLE hInst,
00493
PCL_INSTANCE_INFO *ppcii,
00494 HSZ *phszService,
00495 HSZ hszTopic,
00496 LATOM *plaNormalSvcName,
00497 PCONVCONTEXT *ppCC,
00498 HWND *phwndTarget,
00499 HCONVLIST hConvList)
00500 {
00501
DWORD hszType;
00502
BOOL fError =
FALSE;
00503
00504 *ppcii =
ValidateInstance(
hInst);
00505
if (*ppcii ==
NULL) {
00506
return (
FALSE);
00507 }
00508 hszType =
ValidateHSZ(*phszService);
00509
if (hszType ==
HSZT_INVALID ||
ValidateHSZ(hszTopic) ==
HSZT_INVALID) {
00510
SetLastDDEMLError(*ppcii, DMLERR_INVALIDPARAMETER);
00511
return (
FALSE);
00512 }
00513
if (hszType ==
HSZT_INST_SPECIFIC) {
00514 *phwndTarget =
ParseInstSpecificAtom(
LATOM_FROM_HSZ(*phszService),
00515 plaNormalSvcName);
00516
if (*plaNormalSvcName == 0) {
00517
SetLastDDEMLError(*ppcii, DMLERR_SYS_ERROR);
00518
return (
FALSE);
00519 }
00520 *phszService =
NORMAL_HSZ_FROM_LATOM(*plaNormalSvcName);
00521 }
00522
if (*ppCC ==
NULL) {
00523 *ppCC = &
DefConvContext;
00524
if ((*ppcii)->flags &
IIF_UNICODE) {
00525 (*ppCC)->iCodePage = CP_WINUNICODE;
00526 }
else {
00527 (*ppCC)->iCodePage = CP_WINANSI;
00528 }
00529 }
else try {
00530
if ((*ppCC)->cb >
sizeof(CONVCONTEXT)) {
00531
SetLastDDEMLError(*ppcii, DMLERR_INVALIDPARAMETER);
00532 fError =
TRUE;
00533 }
else if ((*ppCC)->cb <
sizeof(CONVCONTEXT)) {
00534
TempConvContext =
DefConvContext;
00535
00536
00537
00538 RtlCopyMemory(&
TempConvContext, *ppCC, (*ppCC)->cb);
00539 *ppCC = &
TempConvContext;
00540 }
00541 } except(W32ExceptionHandler(
FALSE, RIP_WARNING)) {
00542
SetLastDDEMLError(*ppcii, DMLERR_INVALIDPARAMETER);
00543 fError =
TRUE;
00544 }
00545
if (fError) {
00546
return(
FALSE);
00547 }
00548
if (hConvList != 0 &&
00549 !
ValidateCHandle((HANDLE)hConvList,
HTYPE_CONVERSATION_LIST,
00550 (
DWORD)
InstFromHandle((*ppcii)->hInstClient))) {
00551
return (
FALSE);
00552 }
00553
return (
TRUE);
00554 }
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607 PCL_CONV_INFO ConnectConv(
00608
PCL_INSTANCE_INFO pcii,
00609 LATOM laService,
00610 LATOM laTopic,
00611 HWND hwndTarget,
00612 HWND hwndSkip,
00613 PCONVCONTEXT pCC,
00614 HCONVLIST hConvList,
00615 DWORD clst)
00616 {
00617
INIT_ENUM ie;
00618
PCL_CONV_INFO pci;
00619
PCONV_INFO pcoi;
00620
GATOM gaService, gaTopic;
00621
00622
CheckDDECritIn;
00623
00624
if (hwndTarget && hwndTarget == hwndSkip) {
00625
return(
NULL);
00626 }
00627
00628
LeaveDDECrit;
00629
CheckDDECritOut;
00630
00631
if (pcii->
flags &
IIF_UNICODE) {
00632 ie.
hwndClient = CreateWindowW((LPWSTR)(
gpsi->
atomSysClass[
ICLS_DDEMLCLIENTW]),
00633
L"",
00634 WS_CHILD,
00635 0, 0, 0, 0,
00636 pcii->
hwndMother,
00637 (HMENU)0,
00638 (HANDLE)0,
00639 (
LPVOID)
NULL);
00640 }
else {
00641 ie.
hwndClient = CreateWindowA((LPSTR)(
gpsi->
atomSysClass[
ICLS_DDEMLCLIENTA]),
00642
"",
00643 WS_CHILD,
00644 0, 0, 0, 0,
00645 pcii->
hwndMother,
00646 (HMENU)0,
00647 (HANDLE)0,
00648 (
LPVOID)
NULL);
00649 }
00650
00651
EnterDDECrit;
00652
00653
if (ie.
hwndClient == 0) {
00654
return (
NULL);
00655 }
00656
00657
if (pCC !=
NULL) {
00658
if (!
NtUserDdeSetQualityOfService(ie.
hwndClient, &(pCC->qos),
NULL)) {
00659
SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR);
00660
goto Error;
00661 }
00662 }
00663
00664
00665
00666
SetConvContext(ie.
hwndClient, (LONG *)pCC);
00667 SetWindowLong(ie.
hwndClient,
GWL_CONVSTATE, clst);
00668
SetWindowLongPtr(ie.
hwndClient,
GWLP_SHINST, (LONG_PTR)pcii->
hInstServer);
00669
SetWindowLongPtr(ie.
hwndClient,
GWLP_CHINST, (LONG_PTR)pcii->
hInstClient);
00670
00671 gaService =
LocalToGlobalAtom(laService);
00672 gaTopic =
LocalToGlobalAtom(laTopic);
00673 ie.
lParam = MAKELONG(gaService, gaTopic);
00674
if (!hwndTarget) {
00675 ie.
hwndSkip = hwndSkip;
00676 ie.
laServiceRequested = laService;
00677 ie.
laTopic = laTopic;
00678 ie.
hConvList = hConvList;
00679 ie.
clst = clst;
00680 }
00681
00682
LeaveDDECrit;
00683
00684
if (hwndTarget) {
00685
SendMessage(hwndTarget, WM_DDE_INITIATE, (WPARAM)ie.
hwndClient,
00686 ie.
lParam);
00687 }
else {
00688
00689
00690
00691
00692
00693
00694 HWND hwndAgent = FindWindowW(SZ_NDDEAGNT_CLASS, SZ_NDDEAGNT_TITLE);
00695
if (hwndAgent) {
00696
SendMessage(hwndAgent,
00697 WM_DDE_INITIATE, (WPARAM)ie.
hwndClient, ie.
lParam);
00698 }
00699
EnumWindows((WNDENUMPROC)
InitiateEnumerationProc, (LPARAM)&ie);
00700 }
00701
00702
EnterDDECrit;
00703
00704
00705
00706
00707
00708
#if DBG
00709
{
00710 WCHAR sz[10];
00711
00712
if (gaService && GlobalGetAtomName(gaService, sz, 10) == 0) {
00713 RIPMSG1(RIP_ERROR,
"Bad Service Atom after Initiate phase: %lX", (
DWORD)gaService);
00714 }
00715
if (gaTopic && GlobalGetAtomName(gaTopic, sz, 10) == 0) {
00716 RIPMSG1(RIP_ERROR,
"Bad Topic Atom after Initiate phase: %lX", (
DWORD)gaTopic);
00717 }
00718 }
00719
#endif // DBG
00720
00721 GlobalDeleteAtom(gaService);
00722 GlobalDeleteAtom(gaTopic);
00723
00724
00725
00726
00727 pci = (
PCL_CONV_INFO)
GetWindowLongPtr(ie.
hwndClient,
GWLP_PCI);
00728
if (pci ==
NULL) {
00729
Error:
00730
LeaveDDECrit;
00731
NtUserDestroyWindow(ie.
hwndClient);
00732
EnterDDECrit;
00733
return (
NULL);
00734 }
00735
00736 SetWindowLong(ie.
hwndClient,
GWL_CONVSTATE,
CLST_CONNECTED);
00737
if (hwndTarget) {
00738
00739
00740
00741 pci->
hwndReconnect = hwndTarget;
00742 UserAssert(pci->
ci.
next ==
NULL);
00743 pci->
ci.
laServiceRequested = laService;
00744
IncLocalAtomCount(laService);
00745 }
00746
00747
if (pcii->
MonitorFlags & MF_CONV) {
00748
for (pcoi = (
PCONV_INFO)pci; pcoi; pcoi = pcoi->
next) {
00749
MONCONV(pcoi,
TRUE);
00750 }
00751 }
00752
return (pci);
00753 }
00754
00755
00756
00757
00758
00759 VOID DisconnectConv(
00760
PCONV_INFO pcoi)
00761 {
00762
PCONV_INFO pcoiNext;
00763
00764
for (; pcoi; pcoi = pcoiNext) {
00765 pcoiNext = pcoi->
next;
00766
ShutdownConversation(pcoi,
FALSE);
00767 }
00768 }
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784 BOOL InitiateEnumerationProc(
00785 HWND hwndTarget,
00786 PINIT_ENUM pie)
00787 {
00788
PCL_CONV_INFO pci;
00789
00790
CheckDDECritOut;
00791
00792
if (hwndTarget == pie->
hwndSkip) {
00793
return (
TRUE);
00794 }
00795
00796
if (pie->
hConvList && pie->
laTopic && pie->
laServiceRequested) {
00797
00798
00799
00800
PCONVLIST pcl;
00801
PCONV_INFO pcoiExisting;
00802
int i;
00803
00804
EnterDDECrit;
00805
00806
00807
00808 pcl = (
PCONVLIST)
ValidateCHandle((HANDLE)pie->
hConvList,
00809
HTYPE_CONVERSATION_LIST,
HINST_ANY);
00810
if (pcl !=
NULL) {
00811
for (i = 0; i < pcl->
chwnd; i++) {
00812
for (pcoiExisting = (
PCONV_INFO)
GetWindowLongPtr(pcl->
ahwnd[i],
GWLP_PCI);
00813 pcoiExisting !=
NULL;
00814 pcoiExisting = pcoiExisting->
next) {
00815
if (pcoiExisting->
state & ST_CONNECTED &&
00816 ((
PCL_CONV_INFO)pcoiExisting)->hwndReconnect == hwndTarget &&
00817 pcoiExisting->
laTopic == pie->
laTopic &&
00818 pcoiExisting->
laService == pie->
laServiceRequested) {
00819
LeaveDDECrit;
00820
return(
TRUE);
00821 }
00822 }
00823 }
00824 }
00825
LeaveDDECrit;
00826 }
00827
00828
CheckDDECritOut;
00829
00830
SendMessage(hwndTarget, WM_DDE_INITIATE, (WPARAM)pie->
hwndClient,
00831 pie->
lParam);
00832
00833
EnterDDECrit;
00834
00835
00836
00837
00838
00839
00840
00841 pci = (
PCL_CONV_INFO)
GetWindowLongPtr(pie->
hwndClient,
GWLP_PCI);
00842
if (pci ==
NULL) {
00843
LeaveDDECrit;
00844
return (
TRUE);
00845 }
00846
00847
while (pci !=
NULL) {
00848
if (pci->
hwndReconnect == 0) {
00849 pci->
hwndReconnect = hwndTarget;
00850
if (pie->
laServiceRequested) {
00851 pci->
ci.
laServiceRequested = pie->
laServiceRequested;
00852
IncLocalAtomCount(pie->
laServiceRequested);
00853 }
00854 }
00855
if (pie->
clst ==
CLST_SINGLE_INITIALIZING) {
00856
break;
00857 }
00858 pci = (
PCL_CONV_INFO)pci->
ci.
next;
00859 }
00860
LeaveDDECrit;
00861
return (pie->
clst ==
CLST_MULT_INITIALIZING);
00862 }
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876 VOID SetCommonStateFlags(
00877 HWND hwndUs,
00878 HWND hwndThem,
00879 PWORD pwFlags)
00880 {
00881
DWORD pidUs, pidThem;
00882
00883
GetWindowThreadProcessId(hwndUs, &pidUs);
00884
GetWindowThreadProcessId(hwndThem, &pidThem);
00885
if (pidUs == pidThem) {
00886 *pwFlags |= ST_INTRA_PROCESS;
00887 }
00888
00889
if (
IsWindowUnicode(hwndUs) &&
IsWindowUnicode(hwndThem)) {
00890 *pwFlags |= ST_UNICODE_EXECUTE;
00891 }
00892 }
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906 HCONV
DdeQueryNextServer(
00907 HCONVLIST hConvList,
00908 HCONV hConvPrev)
00909 {
00910 HCONV hConvRet = 0;
00911
PCONVLIST pcl;
00912 HWND *phwnd;
00913
int i;
00914
PCL_CONV_INFO pci;
00915
PCL_INSTANCE_INFO pcii;
00916
00917
EnterDDECrit;
00918
00919 pcl = (
PCONVLIST)
ValidateCHandle((HANDLE)hConvList,
00920
HTYPE_CONVERSATION_LIST,
HINST_ANY);
00921
if (pcl ==
NULL) {
00922
BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
00923
goto Exit;
00924 }
00925
if (!pcl->
chwnd) {
00926
goto Exit;
00927 }
00928 pcii =
PciiFromHandle((HANDLE)hConvList);
00929
if (pcii ==
NULL) {
00930
BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
00931
goto Exit;
00932 }
00933
00934 pcii->
LastError = DMLERR_NO_ERROR;
00935
00936
do {
00937
00938 hConvRet = 0;
00939
00940
if (hConvPrev == 0) {
00941 pci = (
PCL_CONV_INFO)
GetWindowLongPtr(pcl->
ahwnd[0],
GWLP_PCI);
00942
if (pci ==
NULL) {
00943
goto Exit;
00944 }
00945 hConvPrev = hConvRet = pci->
ci.
hConv;
00946
continue;
00947 }
00948
00949 pci = (
PCL_CONV_INFO)
ValidateCHandle((HANDLE)hConvPrev,
00950
HTYPE_CLIENT_CONVERSATION,
InstFromHandle(hConvList));
00951
if (pci ==
NULL) {
00952 pci = (
PCL_CONV_INFO)
ValidateCHandle((HANDLE)hConvPrev,
00953
HTYPE_ZOMBIE_CONVERSATION,
InstFromHandle(hConvList));
00954
if (pci ==
NULL) {
00955
SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
00956
break;
00957 }
else {
00958
goto ZombieSkip;
00959 }
00960 }
00961
00962
if (pci->
hConvList != hConvList) {
00963
SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
00964
break;
00965 }
00966
00967 ZombieSkip:
00968
00969
if (pci->
ci.
next ==
NULL) {
00970
00971
00972
00973
00974
for (phwnd = pcl->
ahwnd, i = 0; (i + 1) < pcl->
chwnd; i++) {
00975
if (phwnd[i] == pci->
ci.
hwndConv) {
00976 pci = (
PCL_CONV_INFO)
GetWindowLongPtr(phwnd[i + 1],
GWLP_PCI);
00977
if (pci ==
NULL) {
00978
break;
00979 }
00980 hConvPrev = hConvRet = pci->
ci.
hConv;
00981
break;
00982 }
00983 }
00984 }
else {
00985
00986 hConvPrev = hConvRet = pci->
ci.
next->
hConv;
00987 }
00988
00989 }
while (hConvRet &&
TypeFromHandle(hConvRet) ==
HTYPE_ZOMBIE_CONVERSATION);
00990 Exit:
00991
LeaveDDECrit;
00992
return (hConvRet);
00993 }
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008 BOOL DdeDisconnect(
01009 HCONV hConv)
01010 {
01011
BOOL fRet =
FALSE;
01012
PCONV_INFO pcoi;
01013
PCL_INSTANCE_INFO pcii;
01014
01015
CheckDDECritOut;
01016
EnterDDECrit;
01017
01018 pcoi = (
PCONV_INFO)
ValidateCHandle((HANDLE)hConv,
01019
HTYPE_CLIENT_CONVERSATION,
HINST_ANY);
01020
if (pcoi ==
NULL) {
01021 pcoi = (
PCONV_INFO)
ValidateCHandle((HANDLE)hConv,
01022
HTYPE_SERVER_CONVERSATION,
HINST_ANY);
01023 }
01024
if (pcoi ==
NULL) {
01025
BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
01026
goto Exit;
01027 }
01028 pcii =
PciiFromHandle((HANDLE)hConv);
01029
if (pcii ==
NULL) {
01030
BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
01031
goto Exit;
01032 }
01033
if (pcoi->
state & ST_CONNECTED) {
01034
ShutdownConversation(pcoi,
FALSE);
01035 }
01036 fRet =
TRUE;
01037
01038 Exit:
01039
LeaveDDECrit;
01040
return (fRet);
01041 }
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053 BOOL DdeDisconnectList(
01054 HCONVLIST hConvList)
01055 {
01056
BOOL fRet =
FALSE;
01057
PCL_INSTANCE_INFO pcii;
01058
PCONVLIST pcl;
01059
PCONV_INFO pcoi, pcoiNext;
01060
int i;
01061
01062
CheckDDECritOut;
01063
EnterDDECrit;
01064
01065 pcl = (
PCONVLIST)
ValidateCHandle((HANDLE)hConvList,
01066
HTYPE_CONVERSATION_LIST,
HINST_ANY);
01067
if (pcl ==
NULL) {
01068
BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
01069
goto Exit;
01070 }
01071
ValidateConvList(hConvList);
01072 pcii =
PciiFromHandle((HANDLE)hConvList);
01073
if (pcii ==
NULL) {
01074
BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
01075
goto Exit;
01076 }
01077
01078
for(i = pcl->
chwnd - 1; i >= 0; i--) {
01079 pcoi = (
PCONV_INFO)
GetWindowLongPtr(pcl->
ahwnd[i],
GWLP_PCI);
01080
while (pcoi !=
NULL && pcoi->
state & ST_CONNECTED) {
01081 pcoiNext = pcoi->
next;
01082
ShutdownConversation(pcoi,
FALSE);
01083 pcoi = pcoiNext;
01084 }
01085 }
01086
01087
DestroyHandle((HANDLE)hConvList);
01088
DDEMLFree(pcl);
01089 fRet =
TRUE;
01090
01091 Exit:
01092
LeaveDDECrit;
01093
return (fRet);
01094 }
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109 VOID ShutdownConversation(
01110
PCONV_INFO pcoi,
01111 BOOL fMakeCallback)
01112 {
01113
CheckDDECritIn;
01114
01115
if (pcoi->
state & ST_CONNECTED) {
01116 pcoi->
state &= ~ST_CONNECTED;
01117
01118
if (
IsWindow(pcoi->
hwndPartner)) {
01119
PostMessage(pcoi->
hwndPartner, WM_DDE_TERMINATE,
01120 (WPARAM)pcoi->
hwndConv, 0);
01121 }
01122
if (fMakeCallback && !(pcoi->
pcii->
afCmd & CBF_SKIP_DISCONNECTS)) {
01123
DoCallback(pcoi->
pcii, (WORD)XTYP_DISCONNECT, 0, pcoi->
hConv,
01124 0, 0, 0, 0, (pcoi->
state & ST_ISSELF) ? 1
L : 0
L);
01125 }
01126
MONCONV(pcoi,
FALSE);
01127 }
01128
01129
FreeConversationResources(pcoi);
01130 }
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153 VOID UnlinkConvFromOthers(
01154
PCONV_INFO pcoi,
01155 BOOL gGoingZombie)
01156 {
01157
PCONV_INFO pcoiPrev, pcoiFirst, pcoiNow;
01158
PCONVLIST pcl;
01159
int i, cActiveInList = 0;
01160
#ifdef TESTING
01161
DWORD path = 0;
01162
#define ORPATH(x) path |= x;
01163
#else
01164
#define ORPATH(x)
01165
#endif // TESTING
01166
01167
CheckDDECritIn;
01168
01169
01170
01171
01172 pcoiPrev =
NULL;
01173 pcoiFirst = pcoiNow = (
PCONV_INFO)
GetWindowLongPtr(pcoi->
hwndConv,
GWLP_PCI);
01174
01175
#ifdef TESTING
01176
01177
01178
01179
while (pcoiNow !=
NULL) {
01180
if (pcoiNow == pcoi) {
01181
goto FoundIt;
01182 }
01183 pcoiNow = pcoiNow->next;
01184 }
01185 DebugBreak();
01186 FoundIt:
01187 pcoiNow = pcoiFirst;
01188
#endif // TESTING
01189
01190 UserAssert(pcoiFirst);
01191
while (pcoiNow !=
NULL) {
01192
if (
TypeFromHandle(pcoiNow->hConv) !=
HTYPE_ZOMBIE_CONVERSATION) {
01193
ORPATH(1);
01194 cActiveInList++;
01195 }
01196
if (pcoiNow->next == pcoi) {
01197 pcoiPrev = pcoiNow;
01198 }
01199 pcoiNow = pcoiNow->
next;
01200 }
01201
01202
ValidateAllConvLists();
01203
01204
01205
01206
01207
if (!gGoingZombie) {
01208
ORPATH(2);
01209
if (
TypeFromHandle(pcoi->
hConv) !=
HTYPE_ZOMBIE_CONVERSATION) {
01210
ORPATH(4);
01211 cActiveInList--;
01212 }
01213
01214
if (pcoiPrev ==
NULL) {
01215
ORPATH(8);
01216 pcoiFirst = pcoi->
next;
01217
SetWindowLongPtr(pcoi->
hwndConv,
GWLP_PCI, (LONG_PTR)pcoiFirst);
01218 }
else {
01219 pcoiPrev->
next = pcoi->
next;
01220 }
01221 }
01222
01223 UserAssert(pcoiFirst !=
NULL || !cActiveInList);
01224
01225
if (cActiveInList == 0) {
01226
ORPATH(0x10);
01227
if (pcoi->
state & ST_CLIENT) {
01228
ORPATH(0x20);
01229
if (((
PCL_CONV_INFO)pcoi)->hConvList) {
01230
01231
01232
01233 pcl = (
PCONVLIST)
GetHandleData((HANDLE)((
PCL_CONV_INFO)pcoi)->hConvList);
01234
for (i = 0; i < pcl->
chwnd; i++) {
01235
if (pcl->
ahwnd[i] == pcoi->hwndConv) {
01236
ORPATH(0x40);
01237 pcl->
chwnd--;
01238 UserAssert(pcl->
ahwnd[pcl->
chwnd]);
01239 pcl->
ahwnd[i] = pcl->
ahwnd[pcl->
chwnd];
01240
ValidateConvList(((
PCL_CONV_INFO)pcoi)->hConvList);
01241
break;
01242 }
01243 }
01244
ORPATH(0x80);
01245 }
01246 }
else {
01247
01248
01249
01250
ORPATH(0x100);
01251
for (i = 0; i < pcoi->
pcii->
cServerLookupAlloc; i++) {
01252
if (pcoi->
pcii->
aServerLookup[i].
hwndServer == pcoi->
hwndConv) {
01253
ORPATH(0x200);
01254
01255
01256
01257
01258
if (
GetAppCompatFlags2(VERMAX) & GACF2_DDE) {
01259 DeleteAtom(pcoi->
pcii->
aServerLookup[i].
laService);
01260 DeleteAtom(pcoi->
pcii->
aServerLookup[i].
laTopic);
01261 }
01262
01263
if (--(pcoi->
pcii->
cServerLookupAlloc)) {
01264
ORPATH(0x400);
01265 pcoi->
pcii->
aServerLookup[i] =
01266 pcoi->
pcii->
aServerLookup[pcoi->
pcii->
cServerLookupAlloc];
01267 }
else {
01268
DDEMLFree(pcoi->
pcii->
aServerLookup);
01269 pcoi->
pcii->
aServerLookup =
NULL;
01270 }
01271
break;
01272 }
01273 }
01274 }
01275 }
01276
#ifdef TESTING
01277
else {
01278
01279
01280
01281 pcoiNow = pcoiFirst;
01282
while (pcoiNow !=
NULL) {
01283
if (
TypeFromHandle(pcoiNow->hConv) !=
HTYPE_ZOMBIE_CONVERSATION) {
01284
goto Out;
01285 }
01286 pcoiNow = pcoiNow->next;
01287 }
01288 DebugBreak();
01289 Out:
01290 ;
01291 }
01292
#endif // TESTING
01293
01294
ValidateAllConvLists();
01295
ORPATH(0x800);
01296
01297
01298
01299
01300
if (pcoi->
state & ST_CLIENT) {
01301
#ifdef TESTING
01302
01303
01304
01305
01306
if (((
PCL_CONV_INFO)pcoi)->hConvList && !cActiveInList) {
01307
BOOL fFound =
FALSE;
01308
01309 pcl = (
PCONVLIST)
GetHandleData((HANDLE)((
PCL_CONV_INFO)pcoi)->hConvList);
01310
for (i = 0; i < pcl->
chwnd; i++) {
01311
if (pcl->
ahwnd[i] == pcoi->hwndConv) {
01312 fFound =
TRUE;
01313
break;
01314 }
01315 }
01316 UserAssert(!fFound);
01317 }
01318
#endif // TESTING
01319
((
PCL_CONV_INFO)pcoi)->hConvList = 0;
01320 pcoi->
state &= ~ST_INLIST;
01321 }
01322
01323
01324
01325
01326
if (pcoiFirst ==
NULL) {
01327
01328
01329
01330
LeaveDDECrit;
01331
NtUserDestroyWindow(pcoi->
hwndConv);
01332
EnterDDECrit;
01333 }
01334 }
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354 VOID FreeConversationResources(
01355
PCONV_INFO pcoi)
01356 {
01357
PADVISE_LINK paLink;
01358
PDDE_MESSAGE_QUEUE pdmq;
01359
PXACT_INFO pxi;
01360
01361
CheckDDECritIn;
01362
01363
01364
01365
01366
if (pcoi->
cLocks > 0) {
01367 pcoi->
state |= ST_FREE_CONV_RES_NOW;
01368
return;
01369 }
01370
01371
01372
01373
01374 pxi = pcoi->
pxiOut;
01375
while (pxi !=
NULL) {
01376
if (pxi->
flags &
XIF_SYNCHRONOUS) {
01377
01378
01379
01380
01381
01382
PostMessage(pcoi->
hwndConv, WM_TIMER,
TID_TIMEOUT, 0);
01383 pcoi->
state |= ST_FREE_CONV_RES_NOW;
01384
return;
01385 }
01386 pxi = pxi->
next;
01387 }
01388
01389
01390
01391
01392
01393
01394
01395
if (pcoi->
state & ST_INTRA_PROCESS && !(pcoi->
state & ST_TERMINATE_RECEIVED)) {
01396
DestroyHandle((HANDLE)pcoi->
hConv);
01397 pcoi->
hConv = (HCONV)
CreateHandle((ULONG_PTR)pcoi,
HTYPE_ZOMBIE_CONVERSATION,
01398
InstFromHandle(pcoi->hConv));
01399
UnlinkConvFromOthers(pcoi,
TRUE);
01400
return;
01401 }
01402
01403
01404
01405
01406
while (pcoi->
pxiOut !=
NULL) {
01407 (pcoi->
pxiOut->
pfnResponse)(pcoi->
pxiOut, 0, 0);
01408 }
01409
01410
01411
01412
01413
while (pcoi->
dmqOut !=
NULL) {
01414
01415 pdmq = pcoi->
dmqOut;
01416
DumpDDEMessage(!(pcoi->
state & ST_INTRA_PROCESS), pdmq->
msg, pdmq->
lParam);
01417 pcoi->
dmqOut = pcoi->
dmqOut->
next;
01418
if (pcoi->
dmqOut ==
NULL) {
01419 pcoi->
dmqIn =
NULL;
01420 }
01421
DDEMLFree(pdmq);
01422 }
01423
01424
01425
01426
01427 paLink = pcoi->
aLinks;
01428
while (pcoi->
cLinks) {
01429
if (pcoi->
state & ST_CLIENT) {
01430
MONLINK(pcoi->
pcii,
FALSE, paLink->
wType & XTYPF_NODATA,
01431 pcoi->
laService, pcoi->
laTopic,
01432
LocalToGlobalAtom(paLink->
laItem),
01433 paLink->
wFmt,
FALSE,
01434 (HCONV)pcoi->
hwndPartner, (HCONV)pcoi->
hwndConv);
01435 }
else {
01436
MONLINK(pcoi->
pcii,
FALSE, paLink->
wType & XTYPF_NODATA,
01437 pcoi->
laService, pcoi->
laTopic,
01438
LocalToGlobalAtom(paLink->
laItem),
01439 paLink->
wFmt,
TRUE,
01440 (HCONV)pcoi->
hwndConv, (HCONV)pcoi->
hwndPartner);
01441 }
01442
if (!(pcoi->
state & ST_CLIENT)) {
01443
DeleteLinkCount(pcoi->
pcii, paLink->
pLinkCount);
01444 }
01445 DeleteAtom(paLink->
laItem);
01446 paLink++;
01447 pcoi->
cLinks--;
01448 }
01449
if (pcoi->
aLinks) {
01450
DDEMLFree(pcoi->
aLinks);
01451 }
01452
01453
01454
01455
01456 DeleteAtom(pcoi->
laService);
01457 DeleteAtom(pcoi->
laTopic);
01458
if (pcoi->
laServiceRequested) {
01459 DeleteAtom(pcoi->
laServiceRequested);
01460 }
01461
01462
UnlinkConvFromOthers(pcoi,
FALSE);
01463
01464
01465
01466
01467
DestroyHandle((HANDLE)pcoi->
hConv);
01468
01469
DDEMLFree(pcoi);
01470 }
01471
01472
01473
01474 BOOL WaitForZombieTerminate(
01475 HANDLE hData)
01476 {
01477
PCONV_INFO pcoi;
01478 MSG
msg;
01479 HWND hwnd;
01480
BOOL fTerminated;
01481
DWORD fRet = 0;
01482
01483
CheckDDECritOut;
01484
EnterDDECrit;
01485
01486 fTerminated =
FALSE;
01487
while ((pcoi = (
PCONV_INFO)
ValidateCHandle(hData,
01488
HTYPE_ZOMBIE_CONVERSATION,
InstFromHandle(hData))) !=
NULL &&
01489 !(pcoi->
state & ST_TERMINATE_RECEIVED)) {
01490 hwnd = pcoi->
hwndConv;
01491
LeaveDDECrit;
01492
while (
PeekMessage(&
msg, hwnd, WM_DDE_FIRST, WM_DDE_LAST, PM_REMOVE)) {
01493
DispatchMessage(&
msg);
01494
if (
msg.message == WM_DDE_TERMINATE) {
01495 fTerminated =
TRUE;
01496 }
01497 }
01498
if (!fTerminated) {
01499 fRet =
MsgWaitForMultipleObjectsEx(0,
NULL, 100, QS_POSTMESSAGE, 0);
01500
if (fRet == 0xFFFFFFFF) {
01501 RIPMSG0(RIP_WARNING,
"WaitForZombieTerminate: I give up - faking terminate.");
01502
ProcessTerminateMsg(pcoi, pcoi->
hwndPartner);
01503
EnterDDECrit;
01504
return(
FALSE);
01505 }
01506 }
01507
EnterDDECrit;
01508 }
01509
LeaveDDECrit;
01510
return(
TRUE);
01511 }