Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

xact.c File Reference

#include "precomp.h"

Go to the source code of this file.

Functions

HDDEDATA DdeClientTransaction (LPBYTE pData, DWORD cbData, HCONV hConv, HSZ hszItem, UINT wFmt, UINT wType, DWORD ulTimeout, LPDWORD pulResult)
VOID GetConvContext (HWND hwnd, LONG *pl)
VOID SetConvContext (HWND hwnd, LONG *pl)
UINT DdeQueryConvInfo (HCONV hConv, DWORD idTransaction, PCONVINFO pConvInfo)
BOOL DdeSetUserHandle (HCONV hConv, DWORD id, DWORD_PTR hUser)
VOID AbandonTransaction (PCONV_INFO pcoi, PXACT_INFO pxi)
BOOL AbandonEnumerateProc (HWND hwnd, LPARAM idTransaction)
BOOL DdeAbandonTransaction (DWORD idInst, HCONV hConv, DWORD idTransaction)
BOOL UpdateLinkIfChanged (PADVISE_LINK paLink, PXACT_INFO pxi, PCONV_INFO pcoi, PADVISE_LINK paLinkLast, PBOOL pfSwapped, DWORD cLinksToGo)
BOOL DdePostAdvise (DWORD idInst, HSZ hszTopic, HSZ hszItem)
VOID LinkTransaction (PXACT_INFO pxi)
VOID UnlinkTransaction (PXACT_INFO pxi)
BOOL ValidateTransaction (HCONV hConv, HANDLE hXact, PCONV_INFO *ppcoi, PXACT_INFO *ppxi)


Function Documentation

BOOL AbandonEnumerateProc HWND  hwnd,
LPARAM  idTransaction
 

Definition at line 532 of file xact.c.

References AbandonTransaction(), BOOL, GetWindowLongPtr(), GWLP_PCI, tagCONV_INFO::next, tagCONV_INFO::state, and TRUE.

Referenced by DdeAbandonTransaction().

00535 { 00536 PCONV_INFO pcoi; 00537 00538 pcoi = (PCONV_INFO)GetWindowLongPtr(hwnd, GWLP_PCI); 00539 if (!pcoi || !(pcoi->state & ST_CLIENT)) { 00540 return(TRUE); 00541 } 00542 while (pcoi) { 00543 AbandonTransaction(pcoi, (PXACT_INFO)idTransaction); 00544 pcoi = pcoi->next; 00545 } 00546 return(TRUE); 00547 }

VOID AbandonTransaction PCONV_INFO  pcoi,
PXACT_INFO  pxi
 

Definition at line 517 of file xact.c.

References tagXACT_INFO::flags, tagXACT_INFO::next, NULL, tagCONV_INFO::pxiIn, VOID(), and XIF_ABANDONED.

Referenced by AbandonEnumerateProc(), and DdeAbandonTransaction().

00520 { 00521 if (pxi != NULL) { 00522 pxi->flags |= XIF_ABANDONED; 00523 } else { 00524 for (pxi = pcoi->pxiIn; pxi != NULL; pxi = pxi->next) { 00525 pxi->flags |= XIF_ABANDONED; 00526 } 00527 } 00528 }

BOOL DdeAbandonTransaction DWORD  idInst,
HCONV  hConv,
DWORD  idTransaction
 

Definition at line 560 of file xact.c.

References AbandonEnumerateProc(), AbandonTransaction(), BOOL, EnterDDECrit, EnumChildWindows(), FALSE, tagCL_INSTANCE_INFO::hwndMother, LeaveDDECrit, NULL, tagCONV_INFO::pcii, SetLastDDEMLError(), TRUE, ValidateInstance(), and ValidateTransaction().

00564 { 00565 PCONV_INFO pcoi; 00566 PXACT_INFO pxi; 00567 PCL_INSTANCE_INFO pcii; 00568 BOOL fRet = FALSE; 00569 00570 EnterDDECrit; 00571 00572 pcii = ValidateInstance((HANDLE)LongToHandle( idInst )); 00573 00574 if (hConv == 0 && idTransaction == 0) { 00575 EnumChildWindows(pcii->hwndMother, AbandonEnumerateProc, 0); 00576 goto Exit; 00577 } 00578 if (idTransaction == 0) { 00579 idTransaction = QID_SYNC; 00580 } 00581 if (!ValidateTransaction(hConv, (HANDLE)LongToHandle( idTransaction ), &pcoi, &pxi)) { 00582 goto Exit; 00583 } 00584 if (pcii == NULL || pcoi->pcii != pcii) { 00585 SetLastDDEMLError(pcoi->pcii, DMLERR_INVALIDPARAMETER); 00586 goto Exit; 00587 } 00588 AbandonTransaction(pcoi, pxi); 00589 fRet = TRUE; 00590 00591 Exit: 00592 LeaveDDECrit; 00593 return (fRet); 00594 }

HDDEDATA DdeClientTransaction LPBYTE  pData,
DWORD  cbData,
HCONV  hConv,
HSZ  hszItem,
UINT  wFmt,
UINT  wType,
DWORD  ulTimeout,
LPDWORD  pulResult
 

Definition at line 24 of file xact.c.

References tagCL_INSTANCE_INFO::afCmd, AllocAndSetDDEData(), BestSetLastDDEMLError(), BOOL, CallMsgFilter(), CheckDDECritOut, tagCL_CONV_INFO::ci, CI_IN_SYNC_TRANSACTION, tagCL_INSTANCE_INFO::cInDDEMLCallback, ClStartAdvise(), ClStartExecute(), ClStartPoke(), ClStartRequest(), ClStartUnadvise(), CopyDDEData(), CreateHandle(), DDEMLAlloc, DDEMLFree, DdeUninitialize(), DestroyHandle(), DispatchMessage(), DWORD, EnterDDECrit, FALSE, tagXACT_INFO::flags, tagCL_INSTANCE_INFO::flags, tagDDEMLDATA::flags, FreeConversationResources(), FreeDDEData(), tagXACT_INFO::gaItem, GetClientInfo, GetMessage(), tagDDEMLDATA::hDDE, tagXACT_INFO::hDDEResult, tagXACT_INFO::hDDESent, HINST_ANY, tagCL_INSTANCE_INFO::hInstClient, HTYPE_CLIENT_CONVERSATION, HTYPE_DATA_HANDLE, HTYPE_TRANSACTION, tagCONV_INFO::hwndConv, tagXACT_INFO::hXact, IIF_IN_SYNC_XACT, InstFromHandle, InternalCreateDataHandle(), L, LATOM_FROM_HSZ, LeaveDDECrit, LocalToGlobalAtom(), msg, NtUserKillTimer(), NtUserSetTimer(), NULL, tagCONV_INFO::pcii, tagXACT_INFO::pcoi, tagXACT_INFO::pfnResponse, SetLastDDEMLError(), tagCONV_INFO::state, TID_TIMEOUT, TRUE, USERGLOBALLOCK, USERGLOBALUNLOCK, ValidateCHandle(), tagXACT_INFO::wFmt, tagDDE_DATA::wFmt, tagXACT_INFO::wStatus, tagDDE_DATA::wStatus, tagXACT_INFO::wType, XIF_ABANDONED, XIF_COMPLETE, and XIF_SYNCHRONOUS.

00033 { 00034 MSG msg; 00035 PCL_INSTANCE_INFO pcii = NULL; 00036 HDDEDATA hRet = 0; 00037 PCL_CONV_INFO pci; 00038 PDDEMLDATA pdd = NULL; 00039 PXACT_INFO pxi; 00040 BOOL fStarted; 00041 PDDE_DATA pdde; 00042 00043 EnterDDECrit; 00044 00045 pci = (PCL_CONV_INFO)ValidateCHandle((HANDLE)hConv, 00046 HTYPE_CLIENT_CONVERSATION, HINST_ANY); 00047 if (pci == NULL) { 00048 BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER); 00049 goto Exit; 00050 } 00051 pcii = pci->ci.pcii; 00052 if (ulTimeout != TIMEOUT_ASYNC && GetClientInfo()->CI_flags & CI_IN_SYNC_TRANSACTION) { 00053 SetLastDDEMLError(pcii, DMLERR_REENTRANCY); 00054 goto Exit; 00055 } 00056 if (!(pci->ci.state & ST_CONNECTED)) { 00057 SetLastDDEMLError(pcii, DMLERR_NO_CONV_ESTABLISHED); 00058 goto Exit; 00059 } 00060 00061 switch (wType) { 00062 case XTYP_POKE: 00063 case XTYP_ADVSTART: 00064 case XTYP_ADVSTART | XTYPF_NODATA: 00065 case XTYP_ADVSTART | XTYPF_ACKREQ: 00066 case XTYP_ADVSTART | XTYPF_NODATA | XTYPF_ACKREQ: 00067 case XTYP_REQUEST: 00068 case XTYP_ADVSTOP: 00069 if (hszItem == 0) { 00070 SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER); 00071 goto Exit; 00072 } 00073 break; 00074 00075 case XTYP_EXECUTE: // just ignore wFmt & hszItem 00076 break; 00077 00078 default: 00079 SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER); 00080 goto Exit; 00081 } 00082 00083 pxi = DDEMLAlloc(sizeof(XACT_INFO)); 00084 if (pxi == NULL) { 00085 SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR); 00086 goto Exit; 00087 } 00088 00089 switch (wType) { 00090 case XTYP_EXECUTE: 00091 case XTYP_POKE: 00092 if ((LONG)cbData == -1L) { 00093 00094 // We are accepting an existing data handle for export to another 00095 // app. 00096 00097 pdd = (PDDEMLDATA)ValidateCHandle((HANDLE)pData, 00098 HTYPE_DATA_HANDLE, HINST_ANY); 00099 if (pdd == NULL) { 00100 InvParam: 00101 SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER); 00102 DDEMLFree(pxi); 00103 goto Exit; 00104 } 00105 00106 // make sure data handle holds apropriate data for this transaction 00107 00108 if ((pdd->flags & HDATA_EXECUTE && wType != XTYP_EXECUTE) || 00109 (!(pdd->flags & HDATA_EXECUTE) && wType == XTYP_EXECUTE)) { 00110 goto InvParam; 00111 } 00112 00113 // To simplify life, use a copy if this handle is potentially 00114 // a relay or APPOWNED handle. 00115 00116 if (pdd->flags & (HDATA_APPOWNED | HDATA_NOAPPFREE)) { 00117 pxi->hDDESent = CopyDDEData(pdd->hDDE, wType == XTYP_EXECUTE); 00118 if (!pxi->hDDESent) { 00119 MemErr: 00120 DDEMLFree(pxi); 00121 SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR); 00122 goto Exit; 00123 } 00124 USERGLOBALLOCK(pxi->hDDESent, pdde); 00125 if (pdde == NULL) { 00126 FreeDDEData(pxi->hDDESent, TRUE, TRUE); 00127 goto MemErr; 00128 } 00129 pdde->wStatus = DDE_FRELEASE; 00130 USERGLOBALUNLOCK(pxi->hDDESent); 00131 } else { 00132 pxi->hDDESent = pdd->hDDE; 00133 } 00134 00135 // make sure handle has proper format 00136 00137 if (wType == XTYP_POKE) { 00138 USERGLOBALLOCK(pxi->hDDESent, pdde); 00139 if (pdde == NULL) { 00140 goto InvParam; 00141 } 00142 pdde->wFmt = (WORD)wFmt; 00143 USERGLOBALUNLOCK(pxi->hDDESent); 00144 } 00145 00146 } else { // Convert data in buffer into an apropriate hDDE 00147 00148 if (wType == XTYP_POKE) { 00149 pxi->hDDESent = AllocAndSetDDEData(pData, cbData, 00150 DDE_FRELEASE, (WORD)wFmt); 00151 } else { 00152 pxi->hDDESent = AllocAndSetDDEData(pData, cbData, 0, 0); 00153 } 00154 if (!pxi->hDDESent) { 00155 goto MemErr; 00156 } 00157 } 00158 } 00159 00160 // FINALLY - start the transaction 00161 00162 pxi->pcoi = (PCONV_INFO)pci; 00163 pxi->gaItem = LocalToGlobalAtom(LATOM_FROM_HSZ(hszItem)); // pxi copy 00164 pxi->wFmt = (WORD)wFmt; 00165 pxi->wType = (WORD)wType; 00166 00167 switch (wType) { 00168 case XTYP_ADVSTART: 00169 case XTYP_ADVSTART | XTYPF_NODATA: 00170 case XTYP_ADVSTART | XTYPF_ACKREQ: 00171 case XTYP_ADVSTART | XTYPF_NODATA | XTYPF_ACKREQ: 00172 fStarted = ClStartAdvise(pxi); 00173 break; 00174 00175 case XTYP_ADVSTOP: 00176 fStarted = ClStartUnadvise(pxi); 00177 break; 00178 00179 case XTYP_EXECUTE: 00180 fStarted = ClStartExecute(pxi); 00181 break; 00182 00183 case XTYP_POKE: 00184 fStarted = ClStartPoke(pxi); 00185 break; 00186 00187 case XTYP_REQUEST: 00188 fStarted = ClStartRequest(pxi); 00189 } 00190 00191 if (!fStarted) { 00192 // if we copied or allocated data - free it. 00193 if (pxi->hDDESent && (pdd == NULL || pxi->hDDESent != pdd->hDDE)) { 00194 FreeDDEData(pxi->hDDESent, FALSE, TRUE); // free data copy 00195 } 00196 GlobalDeleteAtom(pxi->gaItem); // pxi copy 00197 DDEMLFree(pxi); 00198 goto Exit; 00199 } 00200 00201 if (pdd != NULL && !(pdd->flags & (HDATA_NOAPPFREE | HDATA_APPOWNED))) { 00202 00203 // invalidate given handle on success - unless we copied it because 00204 // the app will either be return ing it from a callback or potentially 00205 // using it again. 00206 00207 DDEMLFree(pdd); 00208 DestroyHandle((HANDLE)pData); 00209 } 00210 00211 if (ulTimeout == TIMEOUT_ASYNC) { 00212 00213 // asynchronous transaction 00214 00215 if (pulResult != NULL) { 00216 pxi->hXact = CreateHandle((ULONG_PTR)pxi, HTYPE_TRANSACTION, 00217 InstFromHandle(pcii->hInstClient)); 00218 *pulResult = HandleToUlong(pxi->hXact); 00219 } 00220 hRet = (HDDEDATA)TRUE; 00221 00222 } else { 00223 00224 // synchronous transaction 00225 00226 GetClientInfo()->CI_flags |= CI_IN_SYNC_TRANSACTION; 00227 pcii->flags |= IIF_IN_SYNC_XACT; 00228 00229 pxi->flags |= XIF_SYNCHRONOUS; 00230 NtUserSetTimer(pci->ci.hwndConv, TID_TIMEOUT, ulTimeout, NULL); 00231 00232 LeaveDDECrit; 00233 CheckDDECritOut; 00234 00235 GetMessage(&msg, (HWND)NULL, 0, 0); 00236 00237 /* 00238 * stay in modal loop until a timeout happens. 00239 */ 00240 while (msg.hwnd != pci->ci.hwndConv || msg.message != WM_TIMER || 00241 (msg.wParam != TID_TIMEOUT)) { 00242 00243 if (!CallMsgFilter(&msg, MSGF_DDEMGR)) 00244 DispatchMessage(&msg); 00245 00246 GetMessage(&msg, (HWND)NULL, 0, 0); 00247 } 00248 00249 EnterDDECrit; 00250 00251 NtUserKillTimer(pci->ci.hwndConv, TID_TIMEOUT); 00252 GetClientInfo()->CI_flags &= ~CI_IN_SYNC_TRANSACTION; 00253 pcii->flags &= ~IIF_IN_SYNC_XACT; 00254 00255 if (pxi->flags & XIF_COMPLETE) { 00256 if (pulResult != NULL) { 00257 *pulResult = pxi->wStatus; // NACK status bits 00258 } 00259 switch (wType) { 00260 case XTYP_ADVSTART: 00261 case XTYP_ADVSTART | XTYPF_NODATA: 00262 case XTYP_ADVSTART | XTYPF_ACKREQ: 00263 case XTYP_ADVSTART | XTYPF_NODATA | XTYPF_ACKREQ: 00264 case XTYP_ADVSTOP: 00265 case XTYP_EXECUTE: 00266 case XTYP_POKE: 00267 hRet = (HDDEDATA)((pxi->wStatus & DDE_FACK) ? TRUE : FALSE); 00268 if (!hRet) { 00269 if (pxi->wStatus & DDE_FBUSY) { 00270 SetLastDDEMLError(pcii, DMLERR_BUSY); 00271 } else { 00272 SetLastDDEMLError(pcii, DMLERR_NOTPROCESSED); 00273 } 00274 } 00275 break; 00276 00277 case XTYP_REQUEST: 00278 if (pxi->hDDEResult == 0) { 00279 hRet = (HDDEDATA)((pxi->wStatus & DDE_FACK) ? TRUE : FALSE); 00280 if (!hRet) { 00281 if (pxi->wStatus & DDE_FBUSY) { 00282 SetLastDDEMLError(pcii, DMLERR_BUSY); 00283 } else { 00284 SetLastDDEMLError(pcii, DMLERR_NOTPROCESSED); 00285 } 00286 } 00287 break; 00288 } 00289 // Note that if the incoming data didn't have the DDE_FRELEASE 00290 // bit set, the transaction code would have made a copy so 00291 // the app is free to keep is as long as he likes. 00292 00293 hRet = InternalCreateDataHandle(pcii, (LPBYTE)pxi->hDDEResult, (DWORD)-1, 0, 00294 HDATA_READONLY, 0, 0); 00295 pxi->hDDEResult = 0; // so cleanup doesn't free it. 00296 } 00297 00298 (pxi->pfnResponse)((struct tagXACT_INFO *)pxi, 0, 0); // cleanup transaction 00299 00300 } else { // Timed out 00301 00302 // abandon the transaction and make it asyncronous so it will 00303 // clean itself up when the response finally comes in. 00304 00305 pxi->flags &= ~XIF_SYNCHRONOUS; 00306 pxi->flags |= XIF_ABANDONED; 00307 00308 switch (wType) { 00309 case XTYP_ADVSTART: 00310 case XTYP_ADVSTART | XTYPF_NODATA: 00311 case XTYP_ADVSTART | XTYPF_ACKREQ: 00312 case XTYP_ADVSTART | XTYPF_NODATA | XTYPF_ACKREQ: 00313 SetLastDDEMLError(pcii, DMLERR_ADVACKTIMEOUT); 00314 break; 00315 case XTYP_ADVSTOP: 00316 SetLastDDEMLError(pcii, DMLERR_UNADVACKTIMEOUT); 00317 break; 00318 case XTYP_EXECUTE: 00319 SetLastDDEMLError(pcii, DMLERR_EXECACKTIMEOUT); 00320 break; 00321 case XTYP_POKE: 00322 SetLastDDEMLError(pcii, DMLERR_POKEACKTIMEOUT); 00323 break; 00324 case XTYP_REQUEST: 00325 SetLastDDEMLError(pcii, DMLERR_DATAACKTIMEOUT); 00326 break; 00327 } 00328 // cleanup of pxi happens when transaction actually completes. 00329 } 00330 } 00331 if (pci->ci.state & ST_FREE_CONV_RES_NOW) { 00332 /* 00333 * The conversation was terminated during the synchronous transaction 00334 * so we need to clean up now that we are out of the loop. 00335 */ 00336 FreeConversationResources((PCONV_INFO)pci); 00337 } 00338 00339 Exit: 00340 /* 00341 * Because this API is capable of blocking DdeUninitialize(), we check 00342 * before exit to see if it needs to be called. 00343 */ 00344 if (pcii != NULL && 00345 (pcii->afCmd & APPCMD_UNINIT_ASAP) && 00346 // !(pcii->flags & IIF_IN_SYNC_XACT) && 00347 !pcii->cInDDEMLCallback) { 00348 DdeUninitialize(HandleToUlong(pcii->hInstClient)); 00349 hRet = 0; 00350 } 00351 LeaveDDECrit; 00352 return (hRet); 00353 }

BOOL DdePostAdvise DWORD  idInst,
HSZ  hszTopic,
HSZ  hszItem
 

Definition at line 665 of file xact.c.

References ADVST_CHANGED, tagCL_INSTANCE_INFO::afCmd, tagCONV_INFO::aLinks, tagCL_INSTANCE_INFO::aServerLookup, BestSetLastDDEMLError(), BOOL, tagSVR_CONV_INFO::ci, tagCL_INSTANCE_INFO::cInDDEMLCallback, tagCONV_INFO::cLinks, tagCONV_INFO::cLocks, tagLINK_COUNT::Count, tagCL_INSTANCE_INFO::cServerLookupAlloc, DDEMLAlloc, DDEMLFree, DdeUninitialize(), EnterDDECrit, FALSE, tagCL_INSTANCE_INFO::flags, FreeConversationResources(), GetWindowLongPtr(), GWLP_PSI, tagCL_INSTANCE_INFO::hInstClient, HSZT_INVALID, tagSERVER_LOOKUP::hwndServer, IIF_IN_SYNC_XACT, tagADVISE_LINK::laItem, tagLINK_COUNT::laItem, LATOM_FROM_HSZ, tagSERVER_LOOKUP::laTopic, tagLINK_COUNT::laTopic, LeaveDDECrit, tagCONV_INFO::next, tagLINK_COUNT::next, NULL, tagCONV_INFO::pcii, tagADVISE_LINK::pLinkCount, tagCL_INSTANCE_INFO::pLinkCount, SetLastDDEMLError(), tagCONV_INFO::state, tagADVISE_LINK::state, tagLINK_COUNT::Total, TRUE, UpdateLinkIfChanged(), ValidateHSZ(), ValidateInstance(), and XACT_INFO.

00669 { 00670 PCL_INSTANCE_INFO pcii; 00671 PSVR_CONV_INFO psi; 00672 PXACT_INFO pxi; 00673 PADVISE_LINK paLink; 00674 BOOL fRet = FALSE, fSwapped, fFound; 00675 int iServer, iLink; 00676 PLINK_COUNT pLinkCount; 00677 #if DBG 00678 int cLinks; 00679 #endif 00680 00681 EnterDDECrit; 00682 00683 pcii = ValidateInstance((HANDLE)LongToHandle( idInst )); 00684 if (pcii == NULL) { 00685 BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER); 00686 goto Exit; 00687 } 00688 if ((ValidateHSZ(hszTopic) == HSZT_INVALID) || 00689 (ValidateHSZ(hszItem) == HSZT_INVALID)) { 00690 SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER); 00691 goto Exit; 00692 } 00693 00694 /* 00695 * Initialize all link counters and check if any links qualify 00696 */ 00697 fFound = FALSE; 00698 for (pLinkCount = pcii->pLinkCount; 00699 pLinkCount; pLinkCount = pLinkCount->next) { 00700 pLinkCount->Count = pLinkCount->Total; 00701 fFound |= pLinkCount->laTopic == LATOM_FROM_HSZ(hszTopic) && 00702 pLinkCount->laItem == LATOM_FROM_HSZ(hszItem); 00703 } 00704 if (!fFound && hszTopic && hszItem) { 00705 fRet = TRUE; 00706 goto Exit; 00707 } 00708 00709 /* 00710 * preallocate incase we are low on memory. 00711 */ 00712 pxi = DDEMLAlloc(sizeof(XACT_INFO)); 00713 if (pxi == NULL) { 00714 SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR); 00715 fRet = FALSE; 00716 goto Exit; 00717 } 00718 00719 /* 00720 * For each server window on the specified topic 00721 */ 00722 for (iServer = 0; iServer < pcii->cServerLookupAlloc; iServer++) { 00723 if (hszTopic == 0 || 00724 pcii->aServerLookup[iServer].laTopic == LATOM_FROM_HSZ(hszTopic)) { 00725 00726 /* 00727 * For each conversation within that window 00728 */ 00729 psi = (PSVR_CONV_INFO)GetWindowLongPtr( 00730 pcii->aServerLookup[iServer].hwndServer, GWLP_PSI); 00731 UserAssert(psi != NULL && psi->ci.pcii == pcii); // sanity check 00732 while (psi != NULL) { 00733 00734 00735 /* 00736 * UpdateLinkIfChanged might leave the critical section so lock this conversation 00737 */ 00738 psi->ci.cLocks++; 00739 00740 #if DBG 00741 /* 00742 * Rememeber the number of links so we can assert if they change during the loop below 00743 */ 00744 cLinks = psi->ci.cLinks; 00745 #endif 00746 /* 00747 * For each active link on the given item... 00748 */ 00749 for (paLink = psi->ci.aLinks, iLink = 0; 00750 iLink < psi->ci.cLinks; paLink++, iLink++) { 00751 if (hszItem == 0 || 00752 paLink->laItem == LATOM_FROM_HSZ(hszItem)) { 00753 00754 // Bit of a hack here. For FACKREQ links, we don't want the server to 00755 // outrun the client so we set the ADVST_WAITING bit till the ack is 00756 // received. When the ack comes in, the protocol code has to search 00757 // the aLinks array again to locate the apropriate link state flags and 00758 // clear the ADVST_WAITING flag. At that time, if the ADVST_CHANGED flag 00759 // is set, it is cleared and another SvStartAdviseUpdate transaction 00760 // is started to get the link up to date. To complicate matters, 00761 // the ACK contains no format information. Thus we need to move 00762 // the Link info to the end of the list so that the right format 00763 // is updated when the ack comes in. 00764 00765 paLink->state |= ADVST_CHANGED; 00766 if (UpdateLinkIfChanged(paLink, pxi, &psi->ci, 00767 &psi->ci.aLinks[psi->ci.cLinks - 1], 00768 &fSwapped, --paLink->pLinkCount->Count)) { 00769 if (fSwapped) { 00770 paLink--; 00771 } 00772 /* 00773 * preallocate for next advise 00774 */ 00775 pxi = DDEMLAlloc(sizeof(XACT_INFO)); 00776 if (pxi == NULL) { 00777 SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR); 00778 /* 00779 * Unlock the conversation 00780 */ 00781 psi->ci.cLocks--; 00782 if ((psi->ci.cLocks == 0) && (psi->ci.state & ST_FREE_CONV_RES_NOW)) { 00783 RIPMSG1(RIP_ERROR, "DdePostAdvise: Conversation terminated. psi:%#p", psi); 00784 FreeConversationResources((PCONV_INFO)psi); 00785 } 00786 goto Exit; 00787 } 00788 } 00789 /* 00790 * We might have left the crit sect... 00791 */ 00792 UserAssert(pcii == ValidateInstance((HANDLE)LongToHandle( idInst ))); 00793 } 00794 } 00795 #if DBG 00796 if (cLinks != psi->ci.cLinks) { 00797 RIPMSG1(RIP_ERROR, "DdePostAdvise: cLinks changed. psi:%#p", psi); 00798 } 00799 #endif 00800 00801 /* 00802 * If the converstaion got nuked, stop working on this conversation chain. 00803 */ 00804 psi->ci.cLocks--; 00805 if ((psi->ci.cLocks == 0) && (psi->ci.state & ST_FREE_CONV_RES_NOW)) { 00806 RIPMSG1(RIP_ERROR, "DdePostAdvise: Conversation terminated. psi:%#p", psi); 00807 FreeConversationResources((PCONV_INFO)psi); 00808 break; 00809 } 00810 00811 psi = (PSVR_CONV_INFO)psi->ci.next; // next conversation 00812 } 00813 } 00814 } 00815 DDEMLFree(pxi); 00816 fRet = TRUE; 00817 00818 Exit: 00819 /* 00820 * Because callbacks are capable of blocking DdeUninitialize(), we check 00821 * before exit to see if it needs to be called. 00822 */ 00823 UserAssert(pcii == ValidateInstance((HANDLE)LongToHandle( idInst ))); 00824 if (pcii != NULL && 00825 pcii->afCmd & APPCMD_UNINIT_ASAP && 00826 !(pcii->flags & IIF_IN_SYNC_XACT) && 00827 !pcii->cInDDEMLCallback) { 00828 DdeUninitialize(HandleToUlong(pcii->hInstClient)); 00829 fRet = TRUE; 00830 } 00831 LeaveDDECrit; 00832 return (fRet); 00833 }

UINT DdeQueryConvInfo HCONV  hConv,
DWORD  idTransaction,
PCONVINFO  pConvInfo
 

Definition at line 411 of file xact.c.

References DefConvContext, EnterDDECrit, FALSE, tagXACT_INFO::gaItem, GetConvContext(), GlobalToLocalAtom(), tagXACT_INFO::hUser, tagCONV_INFO::hUser, tagCONV_INFO::hwndConv, tagCONV_INFO::hwndPartner, tagCONV_INFO::laService, tagCONV_INFO::laServiceRequested, tagCL_INSTANCE_INFO::LastError, tagCONV_INFO::laTopic, LeaveDDECrit, NORMAL_HSZ_FROM_LATOM, NULL, tagCONV_INFO::pcii, SetLastDDEMLError(), tagXACT_INFO::state, tagCONV_INFO::state, TRUE, UINT, ValidateTransaction(), tagXACT_INFO::wFmt, and tagXACT_INFO::wType.

00415 { 00416 PCONV_INFO pcoi; 00417 PXACT_INFO pxi; 00418 CONVINFO ci; 00419 UINT uiRet = 0; 00420 00421 EnterDDECrit; 00422 00423 if (!ValidateTransaction(hConv, (HANDLE)LongToHandle( idTransaction ), &pcoi, &pxi)) { 00424 goto Exit; 00425 } 00426 00427 try { 00428 if (pConvInfo->cb > sizeof(CONVINFO)) { 00429 SetLastDDEMLError(pcoi->pcii, DMLERR_INVALIDPARAMETER); 00430 goto Exit; 00431 } 00432 ci.cb = pConvInfo->cb; 00433 ci.hConvPartner = 0; // no longer supported. 00434 ci.hszSvcPartner = NORMAL_HSZ_FROM_LATOM(pcoi->laService); 00435 ci.hszServiceReq = NORMAL_HSZ_FROM_LATOM(pcoi->laServiceRequested); 00436 ci.hszTopic = NORMAL_HSZ_FROM_LATOM(pcoi->laTopic); 00437 ci.wStatus = pcoi->state; 00438 ci.wLastError = (WORD)pcoi->pcii->LastError; 00439 if (pcoi->state & ST_CLIENT) { 00440 ci.hConvList = ((PCL_CONV_INFO)pcoi)->hConvList; 00441 GetConvContext(pcoi->hwndConv, (LONG *)&ci.ConvCtxt); 00442 } else { 00443 ci.hConvList = 0; 00444 if (pcoi->state & ST_ISLOCAL) { 00445 GetConvContext(pcoi->hwndPartner, (LONG *)&ci.ConvCtxt); 00446 } else { 00447 ci.ConvCtxt = DefConvContext; 00448 } 00449 } 00450 if (pxi == NULL) { 00451 ci.hUser = pcoi->hUser; 00452 ci.hszItem = 0; 00453 ci.wFmt = 0; 00454 ci.wType = 0; 00455 ci.wConvst = XST_CONNECTED; 00456 } else { 00457 ci.hUser = pxi->hUser; 00458 // BUG - not fixable - This will result in extra local atoms 00459 // since we can never know when he is done with them. 00460 ci.hszItem = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom(pxi->gaItem)); 00461 ci.wFmt = pxi->wFmt; 00462 ci.wType = pxi->wType; 00463 ci.wConvst = pxi->state; 00464 } 00465 ci.hwnd = pcoi->hwndConv; 00466 ci.hwndPartner = pcoi->hwndPartner; 00467 RtlCopyMemory((LPSTR)pConvInfo, (LPSTR)&ci, pConvInfo->cb); 00468 } except(W32ExceptionHandler(FALSE, RIP_WARNING)) { 00469 SetLastDDEMLError(pcoi->pcii, DMLERR_INVALIDPARAMETER); 00470 goto Exit; 00471 } 00472 uiRet = TRUE; 00473 00474 Exit: 00475 LeaveDDECrit; 00476 return (uiRet); 00477 }

BOOL DdeSetUserHandle HCONV  hConv,
DWORD  id,
DWORD_PTR  hUser
 

Definition at line 489 of file xact.c.

References BOOL, EnterDDECrit, FALSE, tagXACT_INFO::hUser, tagCONV_INFO::hUser, LeaveDDECrit, NULL, TRUE, and ValidateTransaction().

00493 { 00494 PCONV_INFO pcoi; 00495 PXACT_INFO pxi; 00496 BOOL fRet = FALSE; 00497 00498 EnterDDECrit; 00499 00500 if (!ValidateTransaction(hConv, (HANDLE)LongToHandle( id ), &pcoi, &pxi)) { 00501 goto Exit; 00502 } 00503 if (pxi == NULL) { 00504 pcoi->hUser = hUser; 00505 } else { 00506 pxi->hUser = hUser; 00507 } 00508 fRet = TRUE; 00509 00510 Exit: 00511 LeaveDDECrit; 00512 return (fRet); 00513 }

VOID GetConvContext HWND  hwnd,
LONG *  pl
 

Definition at line 368 of file xact.c.

References GWL_CONVCONTEXT, and VOID().

Referenced by DdeQueryConvInfo(), DdeReconnect(), and ProcessDDEMLInitiate().

00371 { 00372 int i; 00373 00374 for (i = 0; i < sizeof(CONVCONTEXT); i += 4) { 00375 *pl++ = GetWindowLong(hwnd, GWL_CONVCONTEXT + i); 00376 } 00377 }

VOID LinkTransaction PXACT_INFO  pxi  ) 
 

Definition at line 846 of file xact.c.

References CheckDDECritIn, tagXACT_INFO::next, NULL, tagXACT_INFO::pcoi, tagCONV_INFO::pxiIn, tagCONV_INFO::pxiOut, and VOID().

Referenced by ClStartAdvise(), ClStartExecute(), ClStartPoke(), ClStartRequest(), ClStartUnadvise(), and SvStartAdviseUpdate().

00848 { 00849 CheckDDECritIn; 00850 00851 pxi->next = NULL; 00852 if (pxi->pcoi->pxiOut == NULL) { 00853 pxi->pcoi->pxiIn = pxi->pcoi->pxiOut = pxi; 00854 } else { 00855 pxi->pcoi->pxiIn->next = pxi; 00856 pxi->pcoi->pxiIn = pxi; 00857 } 00858 #if DBG 00859 /* 00860 * Temporary check to find stress bug - make sure pxi list is not 00861 * looped on itself. If it is, this loop will never exit and things 00862 * will get investigated. (sanfords) 00863 */ 00864 { 00865 PXACT_INFO pxiT; 00866 00867 for (pxiT = pxi->pcoi->pxiOut; pxiT != NULL; pxiT = pxiT->next) { 00868 ; 00869 } 00870 } 00871 #endif // DBG 00872 }

VOID SetConvContext HWND  hwnd,
LONG *  pl
 

Definition at line 387 of file xact.c.

References GWL_CONVCONTEXT, and VOID().

Referenced by ConnectConv().

00390 { 00391 int i; 00392 00393 for (i = 0; i < sizeof(CONVCONTEXT); i += 4) { 00394 SetWindowLong(hwnd, GWL_CONVCONTEXT + i, *pl++); 00395 } 00396 }

VOID UnlinkTransaction PXACT_INFO  pxi  ) 
 

Definition at line 885 of file xact.c.

References CheckDDECritIn, tagXACT_INFO::next, NULL, tagXACT_INFO::pcoi, tagCONV_INFO::pxiIn, tagCONV_INFO::pxiOut, and VOID().

Referenced by ClRespAdviseAck(), ClRespExecuteAck(), ClRespPokeAck(), ClRespRequestData(), ClRespUnadviseAck(), SvRespAdviseDataAck(), and TransactionComplete().

00887 { 00888 CheckDDECritIn; 00889 if (pxi == pxi->pcoi->pxiOut) { 00890 pxi->pcoi->pxiOut = pxi->next; 00891 if (pxi->next == NULL) { 00892 pxi->pcoi->pxiIn = NULL; 00893 } 00894 } 00895 }

BOOL UpdateLinkIfChanged PADVISE_LINK  paLink,
PXACT_INFO  pxi,
PCONV_INFO  pcoi,
PADVISE_LINK  paLinkLast,
PBOOL  pfSwapped,
DWORD  cLinksToGo
 

Definition at line 611 of file xact.c.

References ADVST_CHANGED, ADVST_WAITING, BOOL, CheckDDECritIn, FALSE, tagXACT_INFO::gaItem, tagADVISE_LINK::laItem, LocalToGlobalAtom(), PBYTE, tagXACT_INFO::pcoi, tagXACT_INFO::pfnResponse, tagADVISE_LINK::state, SvRespAdviseDataAck(), SvStartAdviseUpdate(), TRUE, tagADVISE_LINK::wFmt, tagXACT_INFO::wFmt, tagADVISE_LINK::wType, and tagXACT_INFO::wType.

Referenced by DdePostAdvise(), and SvRespAdviseDataAck().

00618 { 00619 ADVISE_LINK aLinkT; 00620 00621 CheckDDECritIn; 00622 00623 *pfSwapped = FALSE; 00624 if (paLink->state & ADVST_CHANGED && !(paLink->state & ADVST_WAITING)) { 00625 pxi->pfnResponse = SvRespAdviseDataAck; 00626 pxi->pcoi = pcoi; 00627 pxi->gaItem = LocalToGlobalAtom(paLink->laItem); // pxi copy 00628 pxi->wFmt = paLink->wFmt; 00629 pxi->wType = paLink->wType; 00630 paLink->state &= ~ADVST_CHANGED; 00631 if (SvStartAdviseUpdate(pxi, cLinksToGo)) { 00632 if (pxi->wType & DDE_FACKREQ) { 00633 paLink->state |= ADVST_WAITING; 00634 /* 00635 * swap paLink with the last non-moved link to make ack search find 00636 * oldest updated format. 00637 */ 00638 if (paLink != paLinkLast) { 00639 aLinkT = *paLink; 00640 RtlMoveMemory(paLink, paLink + 1, 00641 (PBYTE)paLinkLast - (PBYTE)paLink); 00642 *paLinkLast = aLinkT; 00643 *pfSwapped = TRUE; 00644 } 00645 } 00646 return(TRUE); 00647 } else { 00648 GlobalDeleteAtom(pxi->gaItem); // pxi copy 00649 return(FALSE); 00650 } 00651 } 00652 return(FALSE); 00653 }

BOOL ValidateTransaction HCONV  hConv,
HANDLE  hXact,
PCONV_INFO ppcoi,
PXACT_INFO ppxi
 

Definition at line 909 of file xact.c.

References BestSetLastDDEMLError(), BOOL, FALSE, HINST_ANY, HTYPE_CLIENT_CONVERSATION, HTYPE_SERVER_CONVERSATION, HTYPE_TRANSACTION, InstFromHandle, NULL, SetLastDDEMLError(), TRUE, ValidateCHandle(), and ValidateInstance().

Referenced by DdeAbandonTransaction(), DdeQueryConvInfo(), and DdeSetUserHandle().

00914 { 00915 PCL_INSTANCE_INFO pcii; 00916 00917 *ppcoi = (PCONV_INFO)ValidateCHandle((HANDLE)hConv, 00918 HTYPE_CLIENT_CONVERSATION, HINST_ANY); 00919 if (*ppcoi == NULL) { 00920 *ppcoi = (PCONV_INFO)ValidateCHandle((HANDLE)hConv, 00921 HTYPE_SERVER_CONVERSATION, HINST_ANY); 00922 } 00923 if (*ppcoi == NULL) { 00924 BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER); 00925 return (FALSE); 00926 } 00927 pcii = ValidateInstance((*ppcoi)->pcii->hInstClient); 00928 if (pcii != (*ppcoi)->pcii) { 00929 BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER); 00930 return (FALSE); 00931 } 00932 00933 if (hXact == (HANDLE)IntToPtr( QID_SYNC )) { 00934 *ppxi = NULL; 00935 } else { 00936 *ppxi = (PXACT_INFO)ValidateCHandle(hXact, HTYPE_TRANSACTION, 00937 InstFromHandle((*ppcoi)->pcii->hInstClient)); 00938 if (*ppxi == NULL) { 00939 SetLastDDEMLError((*ppcoi)->pcii, DMLERR_INVALIDPARAMETER); 00940 return (FALSE); 00941 } 00942 } 00943 return (TRUE); 00944 }


Generated on Sat May 15 19:46:10 2004 for test by doxygen 1.3.7