Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
87458a5c
Commit
87458a5c
authored
Jul 08, 2005
by
Dmitry Timoshkov
Committed by
Alexandre Julliard
Jul 08, 2005
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add DDE transaction test, make it pass under Wine.
parent
0e8e5c30
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
471 additions
and
120 deletions
+471
-120
dde_client.c
dlls/user/dde_client.c
+116
-75
dde_misc.c
dlls/user/dde_misc.c
+17
-13
dde_private.h
dlls/user/dde_private.h
+6
-3
dde_server.c
dlls/user/dde_server.c
+55
-24
ddeml16.c
dlls/user/ddeml16.c
+2
-1
dde.c
dlls/user/tests/dde.c
+275
-4
No files found.
dlls/user/dde_client.c
View file @
87458a5c
...
...
@@ -40,7 +40,8 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
ddeml
);
static
LRESULT
CALLBACK
WDML_ClientProc
(
HWND
,
UINT
,
WPARAM
,
LPARAM
);
/* only for one client, not conv list */
const
WCHAR
WDML_szClientConvClass
[]
=
{
'W'
,
'i'
,
'n'
,
'e'
,
'D'
,
'd'
,
'e'
,
'C'
,
'l'
,
'i'
,
'e'
,
'n'
,
't'
,
0
};
const
char
WDML_szClientConvClassA
[]
=
"WineDdeClientA"
;
const
WCHAR
WDML_szClientConvClassW
[]
=
{
'W'
,
'i'
,
'n'
,
'e'
,
'D'
,
'd'
,
'e'
,
'C'
,
'l'
,
'i'
,
'e'
,
'n'
,
't'
,
'W'
,
0
};
/******************************************************************************
* DdeConnectList [USER32.@] Establishes conversation with DDE servers
...
...
@@ -99,7 +100,6 @@ HCONV WINAPI DdeConnect(DWORD idInst, HSZ hszService, HSZ hszTopic,
WDML_INSTANCE
*
pInstance
;
WDML_CONV
*
pConv
=
NULL
;
ATOM
aSrv
=
0
,
aTpc
=
0
;
WNDCLASSEXW
wndclass
;
TRACE
(
"(0x%lx,%p,%p,%p)
\n
"
,
idInst
,
hszService
,
hszTopic
,
pCC
);
...
...
@@ -122,22 +122,48 @@ HCONV WINAPI DdeConnect(DWORD idInst, HSZ hszService, HSZ hszTopic,
/* we need to establish a conversation with
server, so create a window for it */
wndclass
.
cbSize
=
sizeof
(
wndclass
);
wndclass
.
style
=
0
;
wndclass
.
lpfnWndProc
=
WDML_ClientProc
;
wndclass
.
cbClsExtra
=
0
;
wndclass
.
cbWndExtra
=
2
*
sizeof
(
ULONG_PTR
);
wndclass
.
hInstance
=
0
;
wndclass
.
hIcon
=
0
;
wndclass
.
hCursor
=
0
;
wndclass
.
hbrBackground
=
0
;
wndclass
.
lpszMenuName
=
NULL
;
wndclass
.
lpszClassName
=
WDML_szClientConvClass
;
wndclass
.
hIconSm
=
0
;
RegisterClassExW
(
&
wndclass
);
hwndClient
=
CreateWindowW
(
WDML_szClientConvClass
,
NULL
,
WS_POPUP
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
);
if
(
pInstance
->
unicode
)
{
WNDCLASSEXW
wndclass
;
wndclass
.
cbSize
=
sizeof
(
wndclass
);
wndclass
.
style
=
0
;
wndclass
.
lpfnWndProc
=
WDML_ClientProc
;
wndclass
.
cbClsExtra
=
0
;
wndclass
.
cbWndExtra
=
2
*
sizeof
(
ULONG_PTR
);
wndclass
.
hInstance
=
0
;
wndclass
.
hIcon
=
0
;
wndclass
.
hCursor
=
0
;
wndclass
.
hbrBackground
=
0
;
wndclass
.
lpszMenuName
=
NULL
;
wndclass
.
lpszClassName
=
WDML_szClientConvClassW
;
wndclass
.
hIconSm
=
0
;
RegisterClassExW
(
&
wndclass
);
hwndClient
=
CreateWindowW
(
WDML_szClientConvClassW
,
NULL
,
WS_POPUP
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
);
}
else
{
WNDCLASSEXA
wndclass
;
wndclass
.
cbSize
=
sizeof
(
wndclass
);
wndclass
.
style
=
0
;
wndclass
.
lpfnWndProc
=
WDML_ClientProc
;
wndclass
.
cbClsExtra
=
0
;
wndclass
.
cbWndExtra
=
2
*
sizeof
(
ULONG_PTR
);
wndclass
.
hInstance
=
0
;
wndclass
.
hIcon
=
0
;
wndclass
.
hCursor
=
0
;
wndclass
.
hbrBackground
=
0
;
wndclass
.
lpszMenuName
=
NULL
;
wndclass
.
lpszClassName
=
WDML_szClientConvClassA
;
wndclass
.
hIconSm
=
0
;
RegisterClassExA
(
&
wndclass
);
hwndClient
=
CreateWindowA
(
WDML_szClientConvClassA
,
NULL
,
WS_POPUP
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
);
}
SetWindowLongPtrW
(
hwndClient
,
GWL_WDML_INSTANCE
,
(
ULONG_PTR
)
pInstance
);
...
...
@@ -188,7 +214,7 @@ HCONV WINAPI DdeConnect(DWORD idInst, HSZ hszService, HSZ hszTopic,
{
memset
(
&
pConv
->
convContext
,
0
,
sizeof
(
pConv
->
convContext
));
pConv
->
convContext
.
cb
=
sizeof
(
pConv
->
convContext
);
pConv
->
convContext
.
iCodePage
=
CP_WINUNICODE
;
pConv
->
convContext
.
iCodePage
=
(
pInstance
->
unicode
)
?
CP_WINUNICODE
:
CP_WINANSI
;
}
theEnd:
...
...
@@ -326,7 +352,7 @@ static WDML_XACT* WDML_ClientQueueAdvise(WDML_CONV* pConv, UINT wType, UINT wFmt
*
* handles the reply to an advise request
*/
static
WDML_QUEUE_STATE
WDML_HandleAdviseReply
(
WDML_CONV
*
pConv
,
MSG
*
msg
,
WDML_XACT
*
pXAct
)
static
WDML_QUEUE_STATE
WDML_HandleAdviseReply
(
WDML_CONV
*
pConv
,
MSG
*
msg
,
WDML_XACT
*
pXAct
,
DWORD
*
ack
)
{
DDEACK
ddeAck
;
UINT_PTR
uiLo
,
uiHi
;
...
...
@@ -346,6 +372,7 @@ static WDML_QUEUE_STATE WDML_HandleAdviseReply(WDML_CONV* pConv, MSG* msg, WDML_
GlobalDeleteAtom
(
uiHi
);
FreeDDElParam
(
WM_DDE_ACK
,
msg
->
lParam
);
if
(
ack
)
*
ack
=
uiLo
;
WDML_ExtractAck
(
uiLo
,
&
ddeAck
);
if
(
ddeAck
.
fAck
)
...
...
@@ -411,7 +438,7 @@ static WDML_XACT* WDML_ClientQueueUnadvise(WDML_CONV* pConv, UINT wFmt, HSZ hszI
*
*
*/
static
WDML_QUEUE_STATE
WDML_HandleUnadviseReply
(
WDML_CONV
*
pConv
,
MSG
*
msg
,
WDML_XACT
*
pXAct
)
static
WDML_QUEUE_STATE
WDML_HandleUnadviseReply
(
WDML_CONV
*
pConv
,
MSG
*
msg
,
WDML_XACT
*
pXAct
,
DWORD
*
ack
)
{
DDEACK
ddeAck
;
UINT_PTR
uiLo
,
uiHi
;
...
...
@@ -431,6 +458,7 @@ static WDML_QUEUE_STATE WDML_HandleUnadviseReply(WDML_CONV* pConv, MSG* msg, WDM
FreeDDElParam
(
WM_DDE_ACK
,
msg
->
lParam
);
GlobalDeleteAtom
(
uiHi
);
if
(
ack
)
*
ack
=
uiLo
;
WDML_ExtractAck
(
uiLo
,
&
ddeAck
);
TRACE
(
"WM_DDE_ACK received while waiting for a timeout
\n
"
);
...
...
@@ -482,7 +510,7 @@ static WDML_XACT* WDML_ClientQueueRequest(WDML_CONV* pConv, UINT wFmt, HSZ hszIt
*
*
*/
static
WDML_QUEUE_STATE
WDML_HandleRequestReply
(
WDML_CONV
*
pConv
,
MSG
*
msg
,
WDML_XACT
*
pXAct
)
static
WDML_QUEUE_STATE
WDML_HandleRequestReply
(
WDML_CONV
*
pConv
,
MSG
*
msg
,
WDML_XACT
*
pXAct
,
DWORD
*
ack
)
{
DDEACK
ddeAck
;
WINE_DDEHEAD
wdh
;
...
...
@@ -498,6 +526,7 @@ static WDML_QUEUE_STATE WDML_HandleRequestReply(WDML_CONV* pConv, MSG* msg, WDML
UnpackDDElParam
(
WM_DDE_ACK
,
msg
->
lParam
,
&
uiLo
,
&
uiHi
);
FreeDDElParam
(
WM_DDE_ACK
,
msg
->
lParam
);
GlobalDeleteAtom
(
uiHi
);
if
(
ack
)
*
ack
=
uiLo
;
WDML_ExtractAck
(
uiLo
,
&
ddeAck
);
pXAct
->
hDdeData
=
0
;
if
(
ddeAck
.
fAck
)
...
...
@@ -550,8 +579,11 @@ static HGLOBAL WDML_BuildExecuteCommand(WDML_CONV* pConv, LPCVOID pData, DWORD c
BOOL
clientUnicode
,
serverUnicode
;
DWORD
memSize
;
clientUnicode
=
IsWindowUnicode
(
pConv
->
hwndClient
);
serverUnicode
=
IsWindowUnicode
(
pConv
->
hwndServer
);
clientUnicode
=
pConv
->
instance
->
unicode
;
TRACE
(
"client %p uses unicode = %d
\n
"
,
pConv
->
hwndClient
,
clientUnicode
);
/* FIXME: how exactly Windows determines what to use for the server side? */
serverUnicode
=
IsWindowUnicode
(
pConv
->
hwndServer
)
&&
IsWindowUnicode
(
pConv
->
hwndClient
);
TRACE
(
"server %p uses unicode = %d
\n
"
,
pConv
->
hwndServer
,
serverUnicode
);
if
(
clientUnicode
==
serverUnicode
)
{
...
...
@@ -646,7 +678,7 @@ static WDML_XACT* WDML_ClientQueueExecute(WDML_CONV* pConv, LPCVOID pData, DWORD
*
*
*/
static
WDML_QUEUE_STATE
WDML_HandleExecuteReply
(
WDML_CONV
*
pConv
,
MSG
*
msg
,
WDML_XACT
*
pXAct
)
static
WDML_QUEUE_STATE
WDML_HandleExecuteReply
(
WDML_CONV
*
pConv
,
MSG
*
msg
,
WDML_XACT
*
pXAct
,
DWORD
*
ack
)
{
DDEACK
ddeAck
;
UINT_PTR
uiLo
,
uiHi
;
...
...
@@ -664,6 +696,7 @@ static WDML_QUEUE_STATE WDML_HandleExecuteReply(WDML_CONV* pConv, MSG* msg, WDML
return
WDML_QS_PASS
;
}
if
(
ack
)
*
ack
=
uiLo
;
WDML_ExtractAck
(
uiLo
,
&
ddeAck
);
pXAct
->
hDdeData
=
(
HDDEDATA
)(
UINT_PTR
)
ddeAck
.
fAck
;
...
...
@@ -725,9 +758,8 @@ static WDML_XACT* WDML_ClientQueuePoke(WDML_CONV* pConv, LPCVOID pData, DWORD cb
*
*
*/
static
WDML_QUEUE_STATE
WDML_HandlePokeReply
(
WDML_CONV
*
pConv
,
MSG
*
msg
,
WDML_XACT
*
pXAct
)
static
WDML_QUEUE_STATE
WDML_HandlePokeReply
(
WDML_CONV
*
pConv
,
MSG
*
msg
,
WDML_XACT
*
pXAct
,
DWORD
*
ack
)
{
DDEACK
ddeAck
;
UINT_PTR
uiLo
,
uiHi
;
HSZ
hsz
;
...
...
@@ -745,7 +777,7 @@ static WDML_QUEUE_STATE WDML_HandlePokeReply(WDML_CONV* pConv, MSG* msg, WDML_XA
FreeDDElParam
(
WM_DDE_ACK
,
msg
->
lParam
);
GlobalDeleteAtom
(
uiHi
);
WDML_ExtractAck
(
uiLo
,
&
ddeAck
)
;
if
(
ack
)
*
ack
=
uiLo
;
GlobalFree
(
pXAct
->
hMem
);
pXAct
->
hDdeData
=
(
HDDEDATA
)
TRUE
;
...
...
@@ -892,7 +924,7 @@ static WDML_QUEUE_STATE WDML_HandleIncomingTerminate(WDML_CONV* pConv, MSG* msg,
*
* handles any incoming reply, and try to match to an already sent request
*/
static
WDML_QUEUE_STATE
WDML_HandleReply
(
WDML_CONV
*
pConv
,
MSG
*
msg
,
HDDEDATA
*
hdd
)
static
WDML_QUEUE_STATE
WDML_HandleReply
(
WDML_CONV
*
pConv
,
MSG
*
msg
,
HDDEDATA
*
hdd
,
DWORD
*
ack
)
{
WDML_XACT
*
pXAct
=
pConv
->
transactions
;
WDML_QUEUE_STATE
qs
;
...
...
@@ -903,19 +935,19 @@ static WDML_QUEUE_STATE WDML_HandleReply(WDML_CONV* pConv, MSG* msg, HDDEDATA* h
switch
(
pXAct
->
ddeMsg
)
{
case
WM_DDE_ADVISE
:
qs
=
WDML_HandleAdviseReply
(
pConv
,
msg
,
pXAct
);
qs
=
WDML_HandleAdviseReply
(
pConv
,
msg
,
pXAct
,
ack
);
break
;
case
WM_DDE_UNADVISE
:
qs
=
WDML_HandleUnadviseReply
(
pConv
,
msg
,
pXAct
);
qs
=
WDML_HandleUnadviseReply
(
pConv
,
msg
,
pXAct
,
ack
);
break
;
case
WM_DDE_EXECUTE
:
qs
=
WDML_HandleExecuteReply
(
pConv
,
msg
,
pXAct
);
qs
=
WDML_HandleExecuteReply
(
pConv
,
msg
,
pXAct
,
ack
);
break
;
case
WM_DDE_REQUEST
:
qs
=
WDML_HandleRequestReply
(
pConv
,
msg
,
pXAct
);
qs
=
WDML_HandleRequestReply
(
pConv
,
msg
,
pXAct
,
ack
);
break
;
case
WM_DDE_POKE
:
qs
=
WDML_HandlePokeReply
(
pConv
,
msg
,
pXAct
);
qs
=
WDML_HandlePokeReply
(
pConv
,
msg
,
pXAct
,
ack
);
break
;
case
WM_DDE_TERMINATE
:
qs
=
WDML_HandleTerminateReply
(
pConv
,
msg
,
pXAct
);
...
...
@@ -981,7 +1013,7 @@ static WDML_QUEUE_STATE WDML_HandleReply(WDML_CONV* pConv, MSG* msg, HDDEDATA* h
* waits until an answer for a sent request is received
* time out is also handled. only used for synchronous transactions
*/
static
HDDEDATA
WDML_SyncWaitTransactionReply
(
HCONV
hConv
,
DWORD
dwTimeout
,
WDML_XACT
*
pXAct
)
static
HDDEDATA
WDML_SyncWaitTransactionReply
(
HCONV
hConv
,
DWORD
dwTimeout
,
WDML_XACT
*
pXAct
,
DWORD
*
ack
)
{
DWORD
dwTime
;
DWORD
err
;
...
...
@@ -1000,33 +1032,47 @@ static HDDEDATA WDML_SyncWaitTransactionReply(HCONV hConv, DWORD dwTimeout, WDML
if
(
MsgWaitForMultipleObjects
(
0
,
NULL
,
FALSE
,
dwTimeout
-
dwTime
,
QS_POSTMESSAGE
)
==
WAIT_OBJECT_0
)
{
BOOL
ret
=
FALSE
;
MSG
msg
;
WDML_CONV
*
pConv
;
HDDEDATA
hdd
;
EnterCriticalSection
(
&
WDML_CritSect
);
pConv
=
WDML_GetConv
(
hConv
,
FALSE
);
if
(
pConv
==
NULL
)
while
(
PeekMessageW
(
&
msg
,
0
,
WM_DDE_FIRST
,
WM_DDE_LAST
,
PM_REMOVE
))
{
LeaveCriticalSection
(
&
WDML_CritSect
);
/* conversation no longer available... return failure */
break
;
}
while
(
PeekMessageW
(
&
msg
,
pConv
->
hwndClient
,
WM_DDE_FIRST
,
WM_DDE_LAST
,
PM_REMOVE
))
{
/* check that either pXAct has been processed or no more xActions are pending */
ret
=
(
pConv
->
transactions
==
pXAct
);
ret
=
WDML_HandleReply
(
pConv
,
&
msg
,
&
hdd
)
==
WDML_QS_HANDLED
&&
(
pConv
->
transactions
==
NULL
||
ret
);
if
(
ret
)
break
;
}
LeaveCriticalSection
(
&
WDML_CritSect
);
if
(
ret
)
{
return
hdd
;
}
WDML_CONV
*
pConv
;
HDDEDATA
hdd
;
EnterCriticalSection
(
&
WDML_CritSect
);
pConv
=
WDML_GetConv
(
hConv
,
FALSE
);
if
(
pConv
==
NULL
)
{
LeaveCriticalSection
(
&
WDML_CritSect
);
/* conversation no longer available... return failure */
return
0
;
}
if
(
msg
.
hwnd
==
pConv
->
hwndClient
)
{
/* check that either pXAct has been processed or no more xActions are pending */
BOOL
ret
=
(
pConv
->
transactions
==
pXAct
);
if
(
WDML_HandleReply
(
pConv
,
&
msg
,
&
hdd
,
ack
)
==
WDML_QS_HANDLED
)
{
TRACE
(
"WDML_HandleReply returned WDML_QS_HANDLED
\n
"
);
ret
=
TRUE
;
}
else
ret
=
(
pConv
->
transactions
==
NULL
||
ret
);
if
(
ret
)
{
pConv
->
instance
->
lastError
=
hdd
?
DMLERR_NO_ERROR
:
DMLERR_NOTPROCESSED
;
LeaveCriticalSection
(
&
WDML_CritSect
);
return
hdd
;
}
}
else
{
LeaveCriticalSection
(
&
WDML_CritSect
);
DispatchMessageW
(
&
msg
);
}
}
}
}
...
...
@@ -1088,11 +1134,7 @@ HDDEDATA WINAPI DdeClientTransaction(LPBYTE pData, DWORD cbData, HCONV hConv, HS
switch
(
wType
)
{
case
XTYP_EXECUTE
:
if
(
hszItem
!=
0
||
wFmt
!=
0
)
{
pConv
->
instance
->
lastError
=
DMLERR_INVALIDPARAMETER
;
goto
theError
;
}
/* Windows simply ignores hszItem and wFmt in this case */
pXAct
=
WDML_ClientQueueExecute
(
pConv
,
pData
,
cbData
);
break
;
case
XTYP_POKE
:
...
...
@@ -1164,14 +1206,10 @@ HDDEDATA WINAPI DdeClientTransaction(LPBYTE pData, DWORD cbData, HCONV hConv, HS
{
DWORD
count
,
i
;
if
(
pdwResult
)
{
*
pdwResult
=
0L
;
}
count
=
WDML_CritSect
.
RecursionCount
;
for
(
i
=
0
;
i
<
count
;
i
++
)
LeaveCriticalSection
(
&
WDML_CritSect
);
hDdeData
=
WDML_SyncWaitTransactionReply
((
HCONV
)
pConv
,
dwTimeout
,
pXAct
);
hDdeData
=
WDML_SyncWaitTransactionReply
((
HCONV
)
pConv
,
dwTimeout
,
pXAct
,
pdwResult
);
for
(
i
=
0
;
i
<
count
;
i
++
)
EnterCriticalSection
(
&
WDML_CritSect
);
}
...
...
@@ -1251,7 +1289,7 @@ static LRESULT CALLBACK WDML_ClientProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPA
((
pConv
=
WDML_GetConvFromWnd
(
hwnd
))
==
NULL
||
pConv
->
wStatus
==
XST_INIT1
))
{
/* In response to WM_DDE_INITIATE, save server window */
WCHAR
buf
[
256
];
char
buf
[
256
];
WDML_INSTANCE
*
pInstance
;
/* note: sent messages do not need packing */
...
...
@@ -1280,8 +1318,10 @@ static LRESULT CALLBACK WDML_ClientProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPA
pConv
->
wConvst
=
XST_INIT1
;
/* check if server is handled by DDEML */
if
(
GetClassNameW
((
HWND
)
wParam
,
buf
,
sizeof
(
buf
)
/
sizeof
(
WCHAR
))
&&
lstrcmpiW
(
buf
,
WDML_szServerConvClass
)
==
0
)
if
((
GetClassNameA
((
HWND
)
wParam
,
buf
,
sizeof
(
buf
))
&&
lstrcmpiA
(
buf
,
WDML_szServerConvClassA
)
==
0
)
||
(
GetClassNameW
((
HWND
)
wParam
,
(
LPWSTR
)
buf
,
sizeof
(
buf
)
/
sizeof
(
WCHAR
))
&&
lstrcmpiW
((
LPWSTR
)
buf
,
WDML_szServerConvClassW
)
==
0
))
{
pConv
->
wStatus
|=
ST_ISLOCAL
;
}
...
...
@@ -1311,14 +1351,15 @@ static LRESULT CALLBACK WDML_ClientProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPA
msg
.
wParam
=
wParam
;
msg
.
lParam
=
lParam
;
WDML_HandleReply
(
pConv
,
&
msg
,
&
hdd
);
WDML_HandleReply
(
pConv
,
&
msg
,
&
hdd
,
NULL
);
}
LeaveCriticalSection
(
&
WDML_CritSect
);
return
0
;
}
return
DefWindowProcW
(
hwnd
,
iMsg
,
wParam
,
lParam
);
return
IsWindowUnicode
(
hwnd
)
?
DefWindowProcW
(
hwnd
,
iMsg
,
wParam
,
lParam
)
:
DefWindowProcA
(
hwnd
,
iMsg
,
wParam
,
lParam
);
}
/*****************************************************************
...
...
@@ -1354,7 +1395,7 @@ BOOL WINAPI DdeDisconnect(HCONV hConv)
LeaveCriticalSection
(
&
WDML_CritSect
);
if
(
PostMessageW
(
pConv
->
hwndServer
,
pXAct
->
ddeMsg
,
(
WPARAM
)
pConv
->
hwndClient
,
pXAct
->
lParam
))
WDML_SyncWaitTransactionReply
(
hConv
,
10000
,
pXAct
);
WDML_SyncWaitTransactionReply
(
hConv
,
10000
,
pXAct
,
NULL
);
for
(
i
=
0
;
i
<
count
;
i
++
)
EnterCriticalSection
(
&
WDML_CritSect
);
ret
=
TRUE
;
...
...
dlls/user/dde_misc.c
View file @
87458a5c
...
...
@@ -341,7 +341,7 @@ static LRESULT CALLBACK WDML_EventProc(HWND hwndEvent, UINT uMsg, WPARAM wParam,
*
*/
UINT
WDML_Initialize
(
LPDWORD
pidInst
,
PFNCALLBACK
pfnCallback
,
DWORD
afCmd
,
DWORD
ulRes
,
BOOL
b16
)
DWORD
afCmd
,
DWORD
ulRes
,
BOOL
b
Unicode
,
BOOL
b
16
)
{
WDML_INSTANCE
*
pInstance
;
WDML_INSTANCE
*
reference_inst
;
...
...
@@ -376,6 +376,7 @@ UINT WDML_Initialize(LPDWORD pidInst, PFNCALLBACK pfnCallback,
pInstance
->
instanceID
=
*
pidInst
;
/* May need to add calling proc Id */
pInstance
->
threadID
=
GetCurrentThreadId
();
pInstance
->
callback
=
*
pfnCallback
;
pInstance
->
unicode
=
bUnicode
;
pInstance
->
win16
=
b16
;
pInstance
->
nodeList
=
NULL
;
/* node will be added later */
pInstance
->
monitorFlags
=
afCmd
&
MF_MASK
;
...
...
@@ -585,7 +586,7 @@ UINT WDML_Initialize(LPDWORD pidInst, PFNCALLBACK pfnCallback,
UINT
WINAPI
DdeInitializeA
(
LPDWORD
pidInst
,
PFNCALLBACK
pfnCallback
,
DWORD
afCmd
,
DWORD
ulRes
)
{
return
WDML_Initialize
(
pidInst
,
pfnCallback
,
afCmd
,
ulRes
,
FALSE
);
return
WDML_Initialize
(
pidInst
,
pfnCallback
,
afCmd
,
ulRes
,
FALSE
,
FALSE
);
}
/******************************************************************************
...
...
@@ -605,7 +606,7 @@ UINT WINAPI DdeInitializeA(LPDWORD pidInst, PFNCALLBACK pfnCallback,
UINT
WINAPI
DdeInitializeW
(
LPDWORD
pidInst
,
PFNCALLBACK
pfnCallback
,
DWORD
afCmd
,
DWORD
ulRes
)
{
return
WDML_Initialize
(
pidInst
,
pfnCallback
,
afCmd
,
ulRes
,
FALSE
);
return
WDML_Initialize
(
pidInst
,
pfnCallback
,
afCmd
,
ulRes
,
TRUE
,
FALSE
);
}
/*****************************************************************
...
...
@@ -1919,7 +1920,7 @@ WDML_CONV* WDML_GetConv(HCONV hConv, BOOL checkConnected)
FIXME
(
"found conv but ain't connected
\n
"
);
return
NULL
;
}
if
(
GetCurrentThreadId
()
!=
pConv
->
instance
->
threadID
)
if
(
!
pConv
->
instance
||
GetCurrentThreadId
()
!=
pConv
->
instance
->
threadID
)
{
FIXME
(
"wrong thread ID
\n
"
);
return
NULL
;
...
...
@@ -2100,6 +2101,7 @@ static BOOL WDML_GetLocalConvInfo(WDML_CONV* pConv, CONVINFO* ci, DWORD id)
/******************************************************************
* DdeQueryConvInfo (USER32.@)
*
* FIXME: Set last DDE error on failure.
*/
UINT
WINAPI
DdeQueryConvInfo
(
HCONV
hConv
,
DWORD
id
,
PCONVINFO
lpConvInfo
)
{
...
...
@@ -2118,18 +2120,20 @@ UINT WINAPI DdeQueryConvInfo(HCONV hConv, DWORD id, PCONVINFO lpConvInfo)
EnterCriticalSection
(
&
WDML_CritSect
);
pConv
=
WDML_GetConv
(
hConv
,
FALSE
);
if
(
pConv
!=
NULL
&&
!
WDML_GetLocalConvInfo
(
pConv
,
&
ci
,
id
)
)
if
(
pConv
!=
NULL
)
{
ret
=
0
;
if
(
!
WDML_GetLocalConvInfo
(
pConv
,
&
ci
,
id
))
ret
=
0
;
}
else
if
((
ULONG_PTR
)
hConv
&
1
)
else
{
pConv
=
WDML_GetConv
((
HCONV
)((
ULONG_PTR
)
hConv
&
~
1
),
FALSE
);
if
(
pConv
!=
NULL
)
{
FIXME
(
"Request on remote conversation information is not implemented yet
\n
"
);
ret
=
0
;
}
if
((
ULONG_PTR
)
hConv
&
1
)
{
pConv
=
WDML_GetConv
((
HCONV
)((
ULONG_PTR
)
hConv
&
~
1
),
FALSE
);
if
(
pConv
!=
NULL
)
FIXME
(
"Request on remote conversation information is not implemented yet
\n
"
);
}
ret
=
0
;
}
LeaveCriticalSection
(
&
WDML_CritSect
);
if
(
ret
!=
0
)
...
...
dlls/user/dde_private.h
View file @
87458a5c
...
...
@@ -153,6 +153,7 @@ typedef struct tagWDML_INSTANCE
DWORD
threadID
;
/* needed to keep instance linked to a unique thread */
BOOL
monitor
;
/* have these two as full Booleans cos they'll be tested frequently */
BOOL
clientOnly
;
/* bit wasteful of space but it will be faster */
BOOL
unicode
;
/* Flag to indicate Win32 API used to initialise */
BOOL
win16
;
/* flag to indicate Win16 API used to initialize */
HSZNode
*
nodeList
;
/* for cleaning upon exit */
PFNCALLBACK
callback
;
...
...
@@ -196,7 +197,7 @@ extern WDML_SERVER* WDML_FindServer(WDML_INSTANCE* pInstance, HSZ hszService, HS
extern
WDML_QUEUE_STATE
WDML_ServerHandle
(
WDML_CONV
*
pConv
,
WDML_XACT
*
pXAct
);
/* called both in DdeClientTransaction and server side. */
extern
UINT
WDML_Initialize
(
LPDWORD
pidInst
,
PFNCALLBACK
pfnCallback
,
DWORD
afCmd
,
DWORD
ulRes
,
BOOL
b16
);
DWORD
afCmd
,
DWORD
ulRes
,
BOOL
b
Unicode
,
BOOL
b
16
);
extern
WDML_CONV
*
WDML_AddConv
(
WDML_INSTANCE
*
pInstance
,
WDML_SIDE
side
,
HSZ
hszService
,
HSZ
hszTopic
,
HWND
hwndClient
,
HWND
hwndServer
);
extern
void
WDML_RemoveConv
(
WDML_CONV
*
pConv
,
WDML_SIDE
side
);
...
...
@@ -242,8 +243,10 @@ static inline void WDML_ExtractAck(WORD status, DDEACK* da)
}
extern
const
WCHAR
WDML_szEventClass
[];
/* class of window for events (aka instance) */
extern
const
WCHAR
WDML_szServerConvClass
[];
/* class of window for server side conv */
extern
const
WCHAR
WDML_szClientConvClass
[];
/* class of window for client side conv */
extern
const
char
WDML_szServerConvClassA
[];
/* ANSI class of window for server side conv */
extern
const
WCHAR
WDML_szServerConvClassW
[];
/* unicode class of window for server side conv */
extern
const
char
WDML_szClientConvClassA
[];
/* ANSI class of window for client side conv */
extern
const
WCHAR
WDML_szClientConvClassW
[];
/* unicode class of window for client side conv */
#define WM_WDML_REGISTER (WM_USER + 0x200)
#define WM_WDML_UNREGISTER (WM_USER + 0x201)
...
...
dlls/user/dde_server.c
View file @
87458a5c
...
...
@@ -39,7 +39,8 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
ddeml
);
static
const
WCHAR
szServerNameClass
[]
=
{
'W'
,
'i'
,
'n'
,
'e'
,
'D'
,
'd'
,
'e'
,
'S'
,
'e'
,
'r'
,
'v'
,
'e'
,
'r'
,
'N'
,
'a'
,
'm'
,
'e'
,
0
};
const
WCHAR
WDML_szServerConvClass
[]
=
{
'W'
,
'i'
,
'n'
,
'e'
,
'D'
,
'd'
,
'e'
,
'S'
,
'e'
,
'r'
,
'v'
,
'e'
,
'r'
,
'C'
,
'o'
,
'n'
,
'v'
,
0
};
const
char
WDML_szServerConvClassA
[]
=
"WineDdeServerConvA"
;
const
WCHAR
WDML_szServerConvClassW
[]
=
{
'W'
,
'i'
,
'n'
,
'e'
,
'D'
,
'd'
,
'e'
,
'S'
,
'e'
,
'r'
,
'v'
,
'e'
,
'r'
,
'C'
,
'o'
,
'n'
,
'v'
,
'W'
,
0
};
static
LRESULT
CALLBACK
WDML_ServerNameProc
(
HWND
,
UINT
,
WPARAM
,
LPARAM
);
static
LRESULT
CALLBACK
WDML_ServerConvProc
(
HWND
,
UINT
,
WPARAM
,
LPARAM
);
...
...
@@ -308,26 +309,53 @@ static WDML_CONV* WDML_CreateServerConv(WDML_INSTANCE* pInstance, HWND hwndClien
{
HWND
hwndServerConv
;
WDML_CONV
*
pConv
;
WNDCLASSEXW
wndclass
;
wndclass
.
cbSize
=
sizeof
(
wndclass
);
wndclass
.
style
=
0
;
wndclass
.
lpfnWndProc
=
WDML_ServerConvProc
;
wndclass
.
cbClsExtra
=
0
;
wndclass
.
cbWndExtra
=
2
*
sizeof
(
ULONG_PTR
);
wndclass
.
hInstance
=
0
;
wndclass
.
hIcon
=
0
;
wndclass
.
hCursor
=
0
;
wndclass
.
hbrBackground
=
0
;
wndclass
.
lpszMenuName
=
NULL
;
wndclass
.
lpszClassName
=
WDML_szServerConvClass
;
wndclass
.
hIconSm
=
0
;
RegisterClassExW
(
&
wndclass
);
hwndServerConv
=
CreateWindowW
(
WDML_szServerConvClass
,
0
,
if
(
pInstance
->
unicode
)
{
WNDCLASSEXW
wndclass
;
wndclass
.
cbSize
=
sizeof
(
wndclass
);
wndclass
.
style
=
0
;
wndclass
.
lpfnWndProc
=
WDML_ServerConvProc
;
wndclass
.
cbClsExtra
=
0
;
wndclass
.
cbWndExtra
=
2
*
sizeof
(
ULONG_PTR
);
wndclass
.
hInstance
=
0
;
wndclass
.
hIcon
=
0
;
wndclass
.
hCursor
=
0
;
wndclass
.
hbrBackground
=
0
;
wndclass
.
lpszMenuName
=
NULL
;
wndclass
.
lpszClassName
=
WDML_szServerConvClassW
;
wndclass
.
hIconSm
=
0
;
RegisterClassExW
(
&
wndclass
);
hwndServerConv
=
CreateWindowW
(
WDML_szServerConvClassW
,
0
,
WS_CHILD
,
0
,
0
,
0
,
0
,
hwndServerName
,
0
,
0
,
0
);
}
else
{
WNDCLASSEXA
wndclass
;
wndclass
.
cbSize
=
sizeof
(
wndclass
);
wndclass
.
style
=
0
;
wndclass
.
lpfnWndProc
=
WDML_ServerConvProc
;
wndclass
.
cbClsExtra
=
0
;
wndclass
.
cbWndExtra
=
2
*
sizeof
(
ULONG_PTR
);
wndclass
.
hInstance
=
0
;
wndclass
.
hIcon
=
0
;
wndclass
.
hCursor
=
0
;
wndclass
.
hbrBackground
=
0
;
wndclass
.
lpszMenuName
=
NULL
;
wndclass
.
lpszClassName
=
WDML_szServerConvClassA
;
wndclass
.
hIconSm
=
0
;
RegisterClassExA
(
&
wndclass
);
hwndServerConv
=
CreateWindowA
(
WDML_szServerConvClassA
,
0
,
WS_CHILD
,
0
,
0
,
0
,
0
,
hwndServerName
,
0
,
0
,
0
);
}
TRACE
(
"Created convServer=%p (nameServer=%p) for instance=%08lx
\n
"
,
hwndServerConv
,
hwndServerName
,
pInstance
->
instanceID
);
...
...
@@ -396,7 +424,7 @@ static LRESULT CALLBACK WDML_ServerNameProc(HWND hwndServer, UINT iMsg, WPARAM w
CONVCONTEXT
cc
;
CONVCONTEXT
*
pcc
=
NULL
;
WDML_CONV
*
pConv
;
WCHAR
buf
[
256
];
char
buf
[
256
];
if
(
GetWindowThreadProcessId
(
hwndClient
,
NULL
)
==
GetWindowThreadProcessId
(
hwndServer
,
NULL
)
&&
WDML_GetInstanceFromWnd
(
hwndClient
)
==
WDML_GetInstanceFromWnd
(
hwndServer
))
...
...
@@ -406,13 +434,15 @@ static LRESULT CALLBACK WDML_ServerNameProc(HWND hwndServer, UINT iMsg, WPARAM w
/* FIXME: so far, we don't grab distant convcontext, so only check if remote is
* handled under DDEML, and if so build a default context
*/
if
(
GetClassNameW
(
hwndClient
,
buf
,
sizeof
(
buf
)
/
sizeof
(
WCHAR
))
&&
lstrcmpiW
(
buf
,
WDML_szClientConvClass
)
==
0
)
if
((
GetClassNameA
(
hwndClient
,
buf
,
sizeof
(
buf
))
&&
lstrcmpiA
(
buf
,
WDML_szClientConvClassA
)
==
0
)
||
(
GetClassNameW
(
hwndClient
,
(
LPWSTR
)
buf
,
sizeof
(
buf
)
/
sizeof
(
WCHAR
))
&&
lstrcmpiW
((
LPWSTR
)
buf
,
WDML_szClientConvClassW
)
==
0
))
{
pcc
=
&
cc
;
memset
(
pcc
,
0
,
sizeof
(
*
pcc
));
pcc
->
cb
=
sizeof
(
*
pcc
);
pcc
->
iCodePage
=
CP_WINUNICODE
;
pcc
->
iCodePage
=
IsWindowUnicode
(
hwndClient
)
?
CP_WINUNICODE
:
CP_WINANSI
;
}
if
((
pInstance
->
CBFflags
&
CBF_FAIL_SELFCONNECTIONS
)
&&
self
)
{
...
...
@@ -976,7 +1006,8 @@ static LRESULT CALLBACK WDML_ServerConvProc(HWND hwndServer, UINT iMsg, WPARAM w
}
if
(
iMsg
<
WM_DDE_FIRST
||
iMsg
>
WM_DDE_LAST
)
{
return
DefWindowProcW
(
hwndServer
,
iMsg
,
wParam
,
lParam
);
return
IsWindowUnicode
(
hwndServer
)
?
DefWindowProcW
(
hwndServer
,
iMsg
,
wParam
,
lParam
)
:
DefWindowProcA
(
hwndServer
,
iMsg
,
wParam
,
lParam
);
}
EnterCriticalSection
(
&
WDML_CritSect
);
...
...
dlls/user/ddeml16.c
View file @
87458a5c
...
...
@@ -151,7 +151,8 @@ HDDEDATA WDML_InvokeCallback16(PFNCALLBACK pfn, UINT uType, UINT uFmt,
UINT16
WINAPI
DdeInitialize16
(
LPDWORD
pidInst
,
PFNCALLBACK16
pfnCallback
,
DWORD
afCmd
,
DWORD
ulRes
)
{
return
WDML_Initialize
(
pidInst
,
(
PFNCALLBACK
)
pfnCallback
,
afCmd
,
ulRes
,
TRUE
);
return
WDML_Initialize
(
pidInst
,
(
PFNCALLBACK
)
pfnCallback
,
afCmd
,
ulRes
,
FALSE
,
TRUE
);
}
/*****************************************************************
...
...
dlls/user/tests/dde.c
View file @
87458a5c
...
...
@@ -23,16 +23,281 @@
#include "wine/test.h"
#include "winbase.h"
#include "winuser.h"
#include "dde.h"
#include "ddeml.h"
#include "winerror.h"
static
HDDEDATA
CALLBACK
DdeCallback
(
UINT
uType
,
UINT
uFmt
,
HCONV
hconv
,
static
const
WCHAR
TEST_DDE_SERVICE
[]
=
{
'T'
,
'e'
,
's'
,
't'
,
'D'
,
'D'
,
'E'
,
'S'
,
'e'
,
'r'
,
'v'
,
'i'
,
'c'
,
'e'
,
0
};
static
const
char
exec_cmdA
[]
=
"ANSI dde command"
;
static
const
WCHAR
exec_cmdW
[]
=
{
'u'
,
'n'
,
'i'
,
'c'
,
'o'
,
'd'
,
'e'
,
' '
,
'd'
,
'd'
,
'e'
,
' '
,
'c'
,
'o'
,
'm'
,
'm'
,
'a'
,
'n'
,
'd'
,
0
};
static
WNDPROC
old_dde_client_wndproc
;
LRESULT
WINAPI
hook_dde_client_wndproc
(
HWND
hwnd
,
UINT
msg
,
WPARAM
wparam
,
LPARAM
lparam
)
{
UINT_PTR
lo
,
hi
;
trace
(
"hook_dde_client_wndproc: %p %04x %08x %08lx
\n
"
,
hwnd
,
msg
,
wparam
,
lparam
);
switch
(
msg
)
{
case
WM_DDE_ACK
:
UnpackDDElParam
(
WM_DDE_ACK
,
lparam
,
&
lo
,
&
hi
);
trace
(
"WM_DDE_ACK: status %04x hglobal %p
\n
"
,
lo
,
(
HGLOBAL
)
hi
);
break
;
default:
break
;
}
return
CallWindowProcA
(
old_dde_client_wndproc
,
hwnd
,
msg
,
wparam
,
lparam
);
}
static
LRESULT
WINAPI
dde_server_wndproc
(
HWND
hwnd
,
UINT
msg
,
WPARAM
wparam
,
LPARAM
lparam
)
{
trace
(
"dde_server_wndproc: %p %04x %08x %08lx
\n
"
,
hwnd
,
msg
,
wparam
,
lparam
);
switch
(
msg
)
{
case
WM_DDE_INITIATE
:
{
ATOM
aService
=
GlobalAddAtomW
(
TEST_DDE_SERVICE
);
trace
(
"server: got WM_DDE_INITIATE from %p with %08lx
\n
"
,
(
HWND
)
wparam
,
lparam
);
if
(
LOWORD
(
lparam
)
==
aService
)
{
ok
(
!
IsWindowUnicode
((
HWND
)
wparam
),
"client should be an ANSI window
\n
"
);
old_dde_client_wndproc
=
(
WNDPROC
)
SetWindowLongPtrA
((
HWND
)
wparam
,
GWLP_WNDPROC
,
(
ULONG_PTR
)
hook_dde_client_wndproc
);
trace
(
"server: sending WM_DDE_ACK to %p
\n
"
,
(
HWND
)
wparam
);
SendMessageW
((
HWND
)
wparam
,
WM_DDE_ACK
,
(
WPARAM
)
hwnd
,
MAKELPARAM
(
aService
,
0
));
}
else
GlobalDeleteAtom
(
aService
);
return
0
;
}
case
WM_DDE_EXECUTE
:
{
DDEACK
ack
;
WORD
status
;
LPCSTR
cmd
;
UINT_PTR
lo
,
hi
;
trace
(
"server: got WM_DDE_EXECUTE from %p with %08lx
\n
"
,
(
HWND
)
wparam
,
lparam
);
UnpackDDElParam
(
WM_DDE_EXECUTE
,
lparam
,
&
lo
,
&
hi
);
trace
(
"%08lx => lo %04x hi %04x
\n
"
,
lparam
,
lo
,
hi
);
ack
.
bAppReturnCode
=
0
;
ack
.
reserved
=
0
;
ack
.
fBusy
=
0
;
cmd
=
GlobalLock
((
HGLOBAL
)
hi
);
if
(
!
cmd
||
(
lstrcmpW
((
LPCWSTR
)
cmd
,
exec_cmdW
)
&&
lstrcmpA
(
cmd
,
exec_cmdA
)))
{
trace
(
"ignoring unknown WM_DDE_EXECUTE command
\n
"
);
/* We have to send a negative acknowledge even if we don't
* accept the command, otherwise Windows goes mad and next time
* we send an acknowledge DDEML drops the connection.
* Not sure how to call it: a bug or a feature.
*/
ack
.
fAck
=
0
;
}
else
ack
.
fAck
=
1
;
GlobalUnlock
((
HGLOBAL
)
hi
);
trace
(
"server: posting %s WM_DDE_ACK to %p
\n
"
,
ack
.
fAck
?
"POSITIVE"
:
"NEGATIVE"
,
(
HWND
)
wparam
);
status
=
*
((
WORD
*
)
&
ack
);
lparam
=
ReuseDDElParam
(
lparam
,
WM_DDE_EXECUTE
,
WM_DDE_ACK
,
status
,
hi
);
PostMessageW
((
HWND
)
wparam
,
WM_DDE_ACK
,
(
WPARAM
)
hwnd
,
lparam
);
return
0
;
}
case
WM_DDE_TERMINATE
:
{
DDEACK
ack
;
WORD
status
;
trace
(
"server: got WM_DDE_TERMINATE from %p with %08lx
\n
"
,
(
HWND
)
wparam
,
lparam
);
ack
.
bAppReturnCode
=
0
;
ack
.
reserved
=
0
;
ack
.
fBusy
=
0
;
ack
.
fAck
=
1
;
trace
(
"server: posting %s WM_DDE_ACK to %p
\n
"
,
ack
.
fAck
?
"POSITIVE"
:
"NEGATIVE"
,
(
HWND
)
wparam
);
status
=
*
((
WORD
*
)
&
ack
);
lparam
=
PackDDElParam
(
WM_DDE_ACK
,
status
,
0
);
PostMessageW
((
HWND
)
wparam
,
WM_DDE_ACK
,
(
WPARAM
)
hwnd
,
lparam
);
return
0
;
}
default:
break
;
}
return
DefWindowProcW
(
hwnd
,
msg
,
wparam
,
lparam
);
}
static
LRESULT
WINAPI
dde_client_wndproc
(
HWND
hwnd
,
UINT
msg
,
WPARAM
wparam
,
LPARAM
lparam
)
{
return
DefWindowProcA
(
hwnd
,
msg
,
wparam
,
lparam
);
}
static
BOOL
create_dde_windows
(
HWND
*
hwnd_client
,
HWND
*
hwnd_server
)
{
WNDCLASSA
wcA
;
WNDCLASSW
wcW
;
static
const
WCHAR
server_class_name
[]
=
{
'd'
,
'd'
,
'e'
,
'_'
,
's'
,
'e'
,
'r'
,
'v'
,
'e'
,
'r'
,
'_'
,
'w'
,
'i'
,
'n'
,
'd'
,
'o'
,
'w'
,
0
};
static
const
char
client_class_name
[]
=
"dde_client_window"
;
memset
(
&
wcW
,
0
,
sizeof
(
wcW
));
wcW
.
lpfnWndProc
=
dde_server_wndproc
;
wcW
.
lpszClassName
=
server_class_name
;
wcW
.
hInstance
=
GetModuleHandleA
(
0
);
if
(
!
RegisterClassW
(
&
wcW
))
return
FALSE
;
memset
(
&
wcA
,
0
,
sizeof
(
wcA
));
wcA
.
lpfnWndProc
=
dde_client_wndproc
;
wcA
.
lpszClassName
=
client_class_name
;
wcA
.
hInstance
=
GetModuleHandleA
(
0
);
assert
(
RegisterClassA
(
&
wcA
));
*
hwnd_server
=
CreateWindowExW
(
0
,
server_class_name
,
NULL
,
WS_POPUP
,
100
,
100
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
GetDesktopWindow
(),
0
,
GetModuleHandleA
(
0
),
NULL
);
assert
(
*
hwnd_server
);
*
hwnd_client
=
CreateWindowExA
(
0
,
client_class_name
,
NULL
,
WS_POPUP
,
100
,
100
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
GetDesktopWindow
(),
0
,
GetModuleHandleA
(
0
),
NULL
);
assert
(
*
hwnd_client
);
trace
(
"server hwnd %p, client hwnd %p
\n
"
,
*
hwnd_server
,
*
hwnd_client
);
ok
(
IsWindowUnicode
(
*
hwnd_server
),
"server has to be a unicode window
\n
"
);
ok
(
!
IsWindowUnicode
(
*
hwnd_client
),
"client has to be an ANSI window
\n
"
);
return
TRUE
;
}
static
HDDEDATA
CALLBACK
client_dde_callback
(
UINT
uType
,
UINT
uFmt
,
HCONV
hconv
,
HSZ
hsz1
,
HSZ
hsz2
,
HDDEDATA
hdata
,
ULONG_PTR
dwData1
,
ULONG_PTR
dwData2
)
{
static
const
char
*
const
cmd_type
[
15
]
=
{
"XTYP_ERROR"
,
"XTYP_ADVDATA"
,
"XTYP_ADVREQ"
,
"XTYP_ADVSTART"
,
"XTYP_ADVSTOP"
,
"XTYP_EXECUTE"
,
"XTYP_CONNECT"
,
"XTYP_CONNECT_CONFIRM"
,
"XTYP_XACT_COMPLETE"
,
"XTYP_POKE"
,
"XTYP_REGISTER"
,
"XTYP_REQUEST"
,
"XTYP_DISCONNECT"
,
"XTYP_UNREGISTER"
,
"XTYP_WILDCONNECT"
};
UINT
type
;
const
char
*
cmd_name
;
type
=
(
uType
&
XTYP_MASK
)
>>
XTYP_SHIFT
;
cmd_name
=
(
type
>=
0
&&
type
<=
14
)
?
cmd_type
[
type
]
:
"unknown"
;
trace
(
"client_dde_callback: %04x (%s) %d %p %p %p %p %08lx %08lx
\n
"
,
uType
,
cmd_name
,
uFmt
,
hconv
,
hsz1
,
hsz2
,
hdata
,
dwData1
,
dwData2
);
return
0
;
}
static
void
test_dde_transaction
(
void
)
{
HSZ
hsz_server
;
DWORD
dde_inst
,
ret
,
err
;
HCONV
hconv
;
HWND
hwnd_client
,
hwnd_server
;
CONVINFO
info
;
HDDEDATA
hdata
;
static
const
char
test_cmd
[]
=
"test dde command"
;
/* server: unicode, client: ansi */
if
(
!
create_dde_windows
(
&
hwnd_client
,
&
hwnd_server
))
return
;
dde_inst
=
0
;
ret
=
DdeInitializeA
(
&
dde_inst
,
client_dde_callback
,
APPCMD_CLIENTONLY
,
0
);
ok
(
ret
==
DMLERR_NO_ERROR
,
"DdeInitializeW failed with error %04lx (%x)
\n
"
,
ret
,
DdeGetLastError
(
dde_inst
));
hsz_server
=
DdeCreateStringHandleW
(
dde_inst
,
TEST_DDE_SERVICE
,
CP_WINUNICODE
);
hconv
=
DdeConnect
(
dde_inst
,
hsz_server
,
0
,
NULL
);
ok
(
hconv
!=
0
,
"DdeConnect error %x
\n
"
,
DdeGetLastError
(
dde_inst
));
err
=
DdeGetLastError
(
dde_inst
);
ok
(
err
==
DMLERR_NO_ERROR
,
"wrong dde error %lx
\n
"
,
err
);
info
.
cb
=
sizeof
(
info
);
ret
=
DdeQueryConvInfo
(
hconv
,
QID_SYNC
,
&
info
);
ok
(
ret
,
"wrong info size %ld, DdeQueryConvInfo error %x
\n
"
,
ret
,
DdeGetLastError
(
dde_inst
));
/* should be CP_WINANSI since we used DdeInitializeA */
ok
(
info
.
ConvCtxt
.
iCodePage
==
CP_WINANSI
,
"wrong iCodePage %d
\n
"
,
info
.
ConvCtxt
.
iCodePage
);
ok
(
!
info
.
hConvPartner
,
"unexpected info.hConvPartner: %p
\n
"
,
info
.
hConvPartner
);
todo_wine
{
ok
((
info
.
wStatus
&
DDE_FACK
),
"unexpected info.wStatus: %04x
\n
"
,
info
.
wStatus
);
}
ok
((
info
.
wStatus
&
(
ST_CONNECTED
|
ST_CLIENT
))
==
(
ST_CONNECTED
|
ST_CLIENT
),
"unexpected info.wStatus: %04x
\n
"
,
info
.
wStatus
);
ok
(
info
.
wConvst
==
XST_CONNECTED
,
"unexpected info.wConvst: %04x
\n
"
,
info
.
wConvst
);
ok
(
info
.
wType
==
0
,
"unexpected info.wType: %04x
\n
"
,
info
.
wType
);
trace
(
"hwnd %p, hwndPartner %p
\n
"
,
info
.
hwnd
,
info
.
hwndPartner
);
trace
(
"sending test client transaction command
\n
"
);
ret
=
0xdeadbeef
;
hdata
=
DdeClientTransaction
((
LPBYTE
)
test_cmd
,
strlen
(
test_cmd
)
+
1
,
hconv
,
(
HSZ
)
0xdead
,
0xbeef
,
XTYP_EXECUTE
,
1000
,
&
ret
);
ok
(
!
hdata
,
"DdeClientTransaction succeeded
\n
"
);
ok
(
ret
==
DDE_FNOTPROCESSED
,
"wrong status code %04lx
\n
"
,
ret
);
err
=
DdeGetLastError
(
dde_inst
);
ok
(
err
==
DMLERR_NOTPROCESSED
,
"wrong dde error %lx
\n
"
,
err
);
trace
(
"sending ANSI client transaction command
\n
"
);
ret
=
0xdeadbeef
;
hdata
=
DdeClientTransaction
((
LPBYTE
)
exec_cmdA
,
lstrlenA
(
exec_cmdA
)
+
1
,
hconv
,
0
,
0
,
XTYP_EXECUTE
,
1000
,
&
ret
);
ok
(
hdata
!=
0
,
"DdeClientTransaction returned %p, error %x
\n
"
,
hdata
,
DdeGetLastError
(
dde_inst
));
ok
(
ret
==
DDE_FACK
,
"wrong status code %04lx
\n
"
,
ret
);
err
=
DdeGetLastError
(
dde_inst
);
ok
(
err
==
DMLERR_NO_ERROR
,
"wrong dde error %lx
\n
"
,
err
);
trace
(
"sending unicode client transaction command
\n
"
);
ret
=
0xdeadbeef
;
hdata
=
DdeClientTransaction
((
LPBYTE
)
exec_cmdW
,
(
lstrlenW
(
exec_cmdW
)
+
1
)
*
sizeof
(
WCHAR
),
hconv
,
0
,
0
,
XTYP_EXECUTE
,
1000
,
&
ret
);
ok
(
hdata
!=
0
,
"DdeClientTransaction returned %p, error %x
\n
"
,
hdata
,
DdeGetLastError
(
dde_inst
));
ok
(
ret
==
DDE_FACK
,
"wrong status code %04lx
\n
"
,
ret
);
err
=
DdeGetLastError
(
dde_inst
);
ok
(
err
==
DMLERR_NO_ERROR
,
"wrong dde error %lx
\n
"
,
err
);
ok
(
DdeDisconnect
(
hconv
),
"DdeDisconnect error %x
\n
"
,
DdeGetLastError
(
dde_inst
));
info
.
cb
=
sizeof
(
info
);
ret
=
DdeQueryConvInfo
(
hconv
,
QID_SYNC
,
&
info
);
ok
(
!
ret
,
"DdeQueryConvInfo should fail
\n
"
);
err
=
DdeGetLastError
(
dde_inst
);
todo_wine
{
ok
(
err
==
DMLERR_INVALIDPARAMETER
,
"wrong dde error %lx
\n
"
,
err
);
}
ok
(
DdeFreeStringHandle
(
dde_inst
,
hsz_server
),
"DdeFreeStringHandle error %x
\n
"
,
DdeGetLastError
(
dde_inst
));
/* This call hangs on win2k SP4.
DdeUninitialize(dde_inst);*/
DestroyWindow
(
hwnd_client
);
DestroyWindow
(
hwnd_server
);
DdeUninitialize
(
dde_inst
);
}
static
void
test_DdeCreateStringHandleW
(
DWORD
dde_inst
,
int
codepage
)
{
static
const
WCHAR
dde_string
[]
=
{
'D'
,
'D'
,
'E'
,
' '
,
'S'
,
't'
,
'r'
,
'i'
,
'n'
,
'g'
,
0
};
...
...
@@ -90,13 +355,13 @@ static void test_DdeCreateStringHandleW(DWORD dde_inst, int codepage)
ok
(
DdeFreeStringHandle
(
dde_inst
,
str_handle
),
"DdeFreeStringHandle failed
\n
"
);
}
START_TEST
(
dde
)
static
void
test_DdeCreateStringHandle
(
void
)
{
DWORD
dde_inst
,
ret
;
dde_inst
=
0xdeadbeef
;
SetLastError
(
0xdeadbeef
);
ret
=
DdeInitializeW
(
&
dde_inst
,
DdeC
allback
,
APPCMD_CLIENTONLY
,
0
);
ret
=
DdeInitializeW
(
&
dde_inst
,
client_dde_c
allback
,
APPCMD_CLIENTONLY
,
0
);
if
(
GetLastError
()
==
ERROR_CALL_NOT_IMPLEMENTED
)
{
trace
(
"Skipping the DDE test on a Win9x platform
\n
"
);
...
...
@@ -107,7 +372,7 @@ START_TEST(dde)
ok
(
DdeGetLastError
(
dde_inst
)
==
DMLERR_INVALIDPARAMETER
,
"expected DMLERR_INVALIDPARAMETER
\n
"
);
dde_inst
=
0
;
ret
=
DdeInitializeW
(
&
dde_inst
,
DdeC
allback
,
APPCMD_CLIENTONLY
,
0
);
ret
=
DdeInitializeW
(
&
dde_inst
,
client_dde_c
allback
,
APPCMD_CLIENTONLY
,
0
);
ok
(
ret
==
DMLERR_NO_ERROR
,
"DdeInitializeW failed with error %04lx (%08x)
\n
"
,
ret
,
DdeGetLastError
(
dde_inst
));
...
...
@@ -117,3 +382,9 @@ START_TEST(dde)
ok
(
DdeUninitialize
(
dde_inst
),
"DdeUninitialize failed
\n
"
);
}
START_TEST
(
dde
)
{
test_DdeCreateStringHandle
();
test_dde_transaction
();
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment