Partial implementation for the following DDE APIs:
DdeCmpStringHandles, DdeCreateStringHandle, DdeFreeStringHandle, DdeQueryString, DdeUninitialize.
This commit is contained in:
parent
9c7c8a4a36
commit
c65f4a4757
|
@ -10,6 +10,11 @@
|
|||
|
||||
#include "wintypes.h"
|
||||
|
||||
/* Codepage Constants
|
||||
*/
|
||||
#define CP_WINANSI 1004
|
||||
#define CP_WINUNICODE 1200
|
||||
|
||||
#define MSGF_DDEMGR 0x8001
|
||||
|
||||
typedef DWORD HCONVLIST;
|
||||
|
@ -61,7 +66,7 @@ HCONV WINAPI DdeQueryNextServer32(HCONVLIST, HCONV);
|
|||
#define DdeQueryNextServer WINELIB_NAME(DdeQueryNextServer)
|
||||
DWORD WINAPI DdeQueryString32A(DWORD, HSZ, LPSTR, DWORD, INT32);
|
||||
DWORD WINAPI DdeQueryString32W(DWORD, HSZ, LPWSTR, DWORD, INT32);
|
||||
#define DdeQueryString WINELIB_NAME(DdeQueryString)
|
||||
#define DdeQueryString WINELIB_NAME_AW(DdeQueryString)
|
||||
BOOL16 WINAPI DdeDisconnectList16(HCONVLIST);
|
||||
BOOL32 WINAPI DdeDisconnectList32(HCONVLIST);
|
||||
#define DdeDisConnectList WINELIB_NAME(DdeDisconnectList)
|
||||
|
@ -110,9 +115,9 @@ BOOL16 WINAPI DdeEnableCallback16(DWORD,HCONV,UINT16);
|
|||
BOOL32 WINAPI DdeEnableCallback32(DWORD,HCONV,UINT32);
|
||||
#define DdeEnableCallback WINELIB_NAME(DdeEnableCallback)
|
||||
int WINAPI DdeCmpStringHandles16(HSZ,HSZ);
|
||||
int WINAPI DdeCmpStringHandles32(HSZ,HSZ);
|
||||
#define DdeCmpStringHandles WINELIB_NAME(DdeCmpStringHandles)
|
||||
|
||||
int WINAPI DdeCmpStringHandles32A(HSZ,HSZ);
|
||||
int WINAPI DdeCmpStringHandles32W(HSZ,HSZ);
|
||||
#define DdeCmpStringHandles WINELIB_NAME_AW(DdeCmpStringHandles)
|
||||
|
||||
HDDEDATA WINAPI DdeNameService16(DWORD,HSZ,HSZ,UINT16);
|
||||
HDDEDATA WINAPI DdeNameService32(DWORD,HSZ,HSZ,UINT32);
|
||||
|
|
356
misc/ddeml.c
356
misc/ddeml.c
|
@ -7,15 +7,142 @@
|
|||
|
||||
/* Only empty stubs for now */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include "ddeml.h"
|
||||
#include "debug.h"
|
||||
#include "windows.h"
|
||||
#include "heap.h"
|
||||
|
||||
/* FIXME: What are these values? */
|
||||
#define DMLERR_NO_ERROR 0
|
||||
|
||||
/* Has defined in atom.c file.
|
||||
*/
|
||||
#define MAX_ATOM_LEN 255
|
||||
|
||||
/* Maximum buffer size ( including the '\0' ).
|
||||
*/
|
||||
#define MAX_BUFFER_LEN (MAX_ATOM_LEN + 1)
|
||||
|
||||
static LONG DDE_current_handle;
|
||||
|
||||
/* This is a simple list to keep track of the strings created
|
||||
* by DdeCreateStringHandle. The list is used to free
|
||||
* the strings whenever DdeUninitialize is called.
|
||||
* This mechanism is not complete and does not handle multiple instances.
|
||||
* Most of the DDE API use a DWORD parameter indicating witch instance
|
||||
* of a given program is calling them. The API are supposed to
|
||||
* associate the data to the instance that created it.
|
||||
*/
|
||||
typedef struct tagHSZNode HSZNode;
|
||||
struct tagHSZNode
|
||||
{
|
||||
HSZNode* next;
|
||||
HSZ hsz;
|
||||
};
|
||||
|
||||
/* Start off the list pointer with a NULL.
|
||||
*/
|
||||
static HSZNode* pHSZNodes = NULL;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* RemoveHSZNodes (INTERNAL)
|
||||
*
|
||||
* Remove a node from the list of HSZ nodes.
|
||||
*/
|
||||
static void RemoveHSZNode( DWORD idInst, HSZ hsz )
|
||||
{
|
||||
HSZNode* pPrev = NULL;
|
||||
HSZNode* pCurrent = NULL;
|
||||
|
||||
/* Set the current node at the start of the list.
|
||||
*/
|
||||
pCurrent = pHSZNodes;
|
||||
/* While we have more nodes.
|
||||
*/
|
||||
while( pCurrent != NULL )
|
||||
{
|
||||
/* If we found the node we were looking for.
|
||||
*/
|
||||
if( pCurrent->hsz == hsz )
|
||||
{
|
||||
/* Remove the node.
|
||||
*/
|
||||
/* If the first node in the list is to to be removed.
|
||||
* Set the global list pointer to the next node.
|
||||
*/
|
||||
if( pCurrent == pHSZNodes )
|
||||
{
|
||||
pHSZNodes = pCurrent->next;
|
||||
}
|
||||
/* Just fix the pointers has to skip the current
|
||||
* node so we can delete it.
|
||||
*/
|
||||
else
|
||||
{
|
||||
pPrev->next = pCurrent->next;
|
||||
}
|
||||
/* Destroy this node.
|
||||
*/
|
||||
free( pCurrent );
|
||||
break;
|
||||
}
|
||||
/* Save the previous node pointer.
|
||||
*/
|
||||
pPrev = pCurrent;
|
||||
/* Move on to the next node.
|
||||
*/
|
||||
pCurrent = pCurrent->next;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FreeAndRemoveHSZNodes (INTERNAL)
|
||||
*
|
||||
* Frees up all the strings still allocated in the list and
|
||||
* remove all the nodes from the list of HSZ nodes.
|
||||
*/
|
||||
static void FreeAndRemoveHSZNodes( DWORD idInst )
|
||||
{
|
||||
/* Free any strings created in this instance.
|
||||
*/
|
||||
while( pHSZNodes != NULL )
|
||||
{
|
||||
DdeFreeStringHandle32( idInst, pHSZNodes->hsz );
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* InsertHSZNode (INTERNAL)
|
||||
*
|
||||
* Insert a node to the head of the list.
|
||||
*/
|
||||
static void InsertHSZNode( DWORD idInst, HSZ hsz )
|
||||
{
|
||||
if( hsz != 0 )
|
||||
{
|
||||
HSZNode* pNew = NULL;
|
||||
/* Create a new node for this HSZ.
|
||||
*/
|
||||
pNew = (HSZNode*) malloc( sizeof( HSZNode ) );
|
||||
if( pNew != NULL )
|
||||
{
|
||||
/* Set the handle value.
|
||||
*/
|
||||
pNew->hsz = hsz;
|
||||
/* Attach the node to the head of the list.
|
||||
*/
|
||||
pNew->next = pHSZNodes;
|
||||
/* The new node is now at the head of the list
|
||||
* so set the global list pointer to it.
|
||||
*/
|
||||
pHSZNodes = pNew;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* DdeInitialize16 (DDEML.2)
|
||||
|
@ -88,7 +215,14 @@ BOOL16 WINAPI DdeUninitialize16( DWORD idInst )
|
|||
*/
|
||||
BOOL32 WINAPI DdeUninitialize32( DWORD idInst )
|
||||
{
|
||||
|
||||
FIXME(ddeml, "(%ld): stub\n", idInst);
|
||||
|
||||
/* Free the nodes that were not freed by this instance
|
||||
* and remove the nodes from the list of HSZ nodes.
|
||||
*/
|
||||
FreeAndRemoveHSZNodes( idInst );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -150,6 +284,9 @@ HCONV WINAPI DdeQueryNextServer32( HCONVLIST hConvList, HCONV hConvPrev )
|
|||
*/
|
||||
DWORD WINAPI DdeQueryString32A(DWORD idInst, HSZ hsz, LPSTR psz, DWORD cchMax, INT32 iCodePage)
|
||||
{
|
||||
DWORD ret = 0;
|
||||
CHAR pString[MAX_BUFFER_LEN];
|
||||
|
||||
FIXME(ddeml,
|
||||
"(%ld, 0x%lx, %p, %ld, %d): stub\n",
|
||||
idInst,
|
||||
|
@ -158,7 +295,21 @@ DWORD WINAPI DdeQueryString32A(DWORD idInst, HSZ hsz, LPSTR psz, DWORD cchMax, I
|
|||
cchMax,
|
||||
iCodePage);
|
||||
|
||||
return 0;
|
||||
if( iCodePage == CP_WINANSI )
|
||||
{
|
||||
/* If psz is null, we have to return only the length
|
||||
* of the string.
|
||||
*/
|
||||
if( psz == NULL )
|
||||
{
|
||||
psz = pString;
|
||||
cchMax = MAX_BUFFER_LEN;
|
||||
}
|
||||
|
||||
ret = GlobalGetAtomName32A( hsz, (LPSTR)psz, cchMax );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
|
@ -166,6 +317,10 @@ DWORD WINAPI DdeQueryString32A(DWORD idInst, HSZ hsz, LPSTR psz, DWORD cchMax, I
|
|||
*/
|
||||
DWORD WINAPI DdeQueryString32W(DWORD idInst, HSZ hsz, LPWSTR psz, DWORD cchMax, INT32 iCodePage)
|
||||
{
|
||||
DWORD ret = 0;
|
||||
WCHAR pString[MAX_BUFFER_LEN];
|
||||
int factor = 1;
|
||||
|
||||
FIXME(ddeml,
|
||||
"(%ld, 0x%lx, %p, %ld, %d): stub\n",
|
||||
idInst,
|
||||
|
@ -174,7 +329,23 @@ DWORD WINAPI DdeQueryString32W(DWORD idInst, HSZ hsz, LPWSTR psz, DWORD cchMax,
|
|||
cchMax,
|
||||
iCodePage);
|
||||
|
||||
return 0;
|
||||
if( iCodePage == CP_WINUNICODE )
|
||||
{
|
||||
/* If psz is null, we have to return only the length
|
||||
* of the string.
|
||||
*/
|
||||
if( psz == NULL )
|
||||
{
|
||||
psz = pString;
|
||||
cchMax = MAX_BUFFER_LEN;
|
||||
/* Note: According to documentation if the psz parameter
|
||||
* was NULL this API must return the length of the string in bytes.
|
||||
*/
|
||||
factor = (int) sizeof(WCHAR)/sizeof(BYTE);
|
||||
}
|
||||
ret = GlobalGetAtomName32W( hsz, (LPWSTR)psz, cchMax ) * factor;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -315,11 +486,19 @@ HSZ WINAPI DdeCreateStringHandle16( DWORD idInst, LPCSTR str, INT16 codepage )
|
|||
* Failure: 0
|
||||
*/
|
||||
HSZ WINAPI DdeCreateStringHandle32A( DWORD idInst, LPCSTR psz, INT32 codepage )
|
||||
{ TRACE(ddeml, "(%ld,%s,%d): stub\n",idInst,debugstr_a(psz),codepage);
|
||||
{
|
||||
HSZ hsz = 0;
|
||||
TRACE(ddeml, "(%ld,%s,%d): stub\n",idInst,debugstr_a(psz),codepage);
|
||||
|
||||
if (codepage==1004) /*fixme: should be CP_WINANSI*/
|
||||
return GlobalAddAtom32A (psz);
|
||||
else
|
||||
if (codepage==CP_WINANSI)
|
||||
{
|
||||
hsz = GlobalAddAtom32A (psz);
|
||||
/* Save the handle so we know to clean it when
|
||||
* uninitialize is called.
|
||||
*/
|
||||
InsertHSZNode( idInst, hsz );
|
||||
return hsz;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -336,9 +515,20 @@ HSZ WINAPI DdeCreateStringHandle32W(
|
|||
LPCWSTR psz, /* [in] Pointer to string */
|
||||
INT32 codepage) /* [in] Code page identifier */
|
||||
{
|
||||
HSZ hsz = 0;
|
||||
|
||||
FIXME(ddeml, "(%ld,%s,%d): stub\n",idInst,debugstr_w(psz),codepage);
|
||||
DDE_current_handle++;
|
||||
return DDE_current_handle;
|
||||
|
||||
if (codepage==CP_WINUNICODE)
|
||||
{
|
||||
hsz = GlobalAddAtom32W (psz);
|
||||
/* Save the handle so we know to clean it when
|
||||
* uninitialize is called.
|
||||
*/
|
||||
InsertHSZNode( idInst, hsz );
|
||||
return hsz;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -357,8 +547,14 @@ BOOL16 WINAPI DdeFreeStringHandle16( DWORD idInst, HSZ hsz )
|
|||
* fail: zero
|
||||
*/
|
||||
BOOL32 WINAPI DdeFreeStringHandle32( DWORD idInst, HSZ hsz )
|
||||
{ TRACE( ddeml, "(%ld,%ld): stub\n",idInst, hsz );
|
||||
return GlobalDeleteAtom (hsz) ? hsz : 0;
|
||||
{
|
||||
TRACE( ddeml, "(%ld,%ld): stub\n",idInst, hsz );
|
||||
/* Remove the node associated with this HSZ.
|
||||
*/
|
||||
RemoveHSZNode( idInst, hsz );
|
||||
/* Free the string associated with this HSZ.
|
||||
*/
|
||||
return GlobalDeleteAtom (hsz) ? 0 : hsz;
|
||||
}
|
||||
|
||||
|
||||
|
@ -381,6 +577,8 @@ BOOL32 WINAPI DdeFreeDataHandle32( HDDEDATA hData )
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* DdeKeepStringHandle16 (DDEML.24)
|
||||
*/
|
||||
|
@ -617,16 +815,144 @@ UINT32 WINAPI DdeGetLastError32( DWORD idInst )
|
|||
*/
|
||||
int WINAPI DdeCmpStringHandles16( HSZ hsz1, HSZ hsz2 )
|
||||
{
|
||||
return DdeCmpStringHandles32(hsz1, hsz2);
|
||||
return DdeCmpStringHandles32A(hsz1, hsz2);
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
* DdeCmpStringHandles32 (USER32.91)
|
||||
* DdeCmpStringHandles32A (USER32.91)
|
||||
*
|
||||
* Compares the value of two string handles. This comparison is
|
||||
* not case sensitive.
|
||||
*
|
||||
* Returns:
|
||||
* -1 The value of hsz1 is zero or less than hsz2
|
||||
* 0 The values of hsz 1 and 2 are the same or both zero.
|
||||
* 1 The value of hsz2 is zero of less than hsz1
|
||||
*/
|
||||
int WINAPI DdeCmpStringHandles32( HSZ hsz1, HSZ hsz2 )
|
||||
int WINAPI DdeCmpStringHandles32A( HSZ hsz1, HSZ hsz2 )
|
||||
{
|
||||
FIXME( ddeml, "(0x%lx, 0x%lx): stub\n", hsz1, hsz2 );
|
||||
return 0;
|
||||
CHAR psz1[MAX_BUFFER_LEN];
|
||||
CHAR psz2[MAX_BUFFER_LEN];
|
||||
int ret = 0;
|
||||
int ret1, ret2;
|
||||
|
||||
TRACE( ddeml, "handle 1, handle 2\n" );
|
||||
|
||||
ret1 = GlobalGetAtomName32A( hsz1, psz1, MAX_BUFFER_LEN );
|
||||
ret2 = GlobalGetAtomName32A( hsz2, psz2, MAX_BUFFER_LEN );
|
||||
/* Make sure we found both strings.
|
||||
*/
|
||||
if( ret1 == 0 && ret2 == 0 )
|
||||
{
|
||||
/* If both are not found, return both "zero strings".
|
||||
*/
|
||||
ret = 0;
|
||||
}
|
||||
else if( ret1 == 0 )
|
||||
{
|
||||
/* If hsz1 is a not found, return hsz1 is "zero string".
|
||||
*/
|
||||
ret = -1;
|
||||
}
|
||||
else if( ret2 == 0 )
|
||||
{
|
||||
/* If hsz2 is a not found, return hsz2 is "zero string".
|
||||
*/
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Compare the two strings we got ( case insensitive ).
|
||||
*/
|
||||
ret = strcasecmp( psz1, psz2 );
|
||||
/* Since strcmp returns any number smaller than
|
||||
* 0 when the first string is found to be less than
|
||||
* the second one we must make sure we are returning
|
||||
* the proper values.
|
||||
*/
|
||||
if( ret < 0 )
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
else if( ret > 0 )
|
||||
{
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
* DdeCmpStringHandles32W (USER32.623)
|
||||
*
|
||||
* Compares the value of two string handles. This comparison is
|
||||
* not case sensitive.
|
||||
*
|
||||
* Returns:
|
||||
* -1 The value of hsz1 is zero or less than hsz2
|
||||
* 0 The values of hsz 1 and 2 are the same or both zero.
|
||||
* 1 The value of hsz2 is zero of less than hsz1
|
||||
*/
|
||||
int WINAPI DdeCmpStringHandles32W( HSZ hsz1, HSZ hsz2 )
|
||||
{
|
||||
WCHAR pwsz1[MAX_BUFFER_LEN];
|
||||
WCHAR pwsz2[MAX_BUFFER_LEN];
|
||||
int ret = 0;
|
||||
int ret1, ret2;
|
||||
|
||||
TRACE( ddeml, "handle 1, handle 2\n" );
|
||||
|
||||
ret1 = GlobalGetAtomName32W( hsz1, pwsz1, MAX_BUFFER_LEN );
|
||||
ret2 = GlobalGetAtomName32W( hsz2, pwsz2, MAX_BUFFER_LEN );
|
||||
/* Make sure we found both strings.
|
||||
*/
|
||||
if( ret1 == 0 && ret2 == 0 )
|
||||
{
|
||||
/* If both are not found, return both "zero strings".
|
||||
*/
|
||||
ret = 0;
|
||||
}
|
||||
else if( ret1 == 0 )
|
||||
{
|
||||
/* If hsz1 is a not found, return hsz1 is "zero string".
|
||||
*/
|
||||
ret = -1;
|
||||
}
|
||||
else if( ret2 == 0 )
|
||||
{
|
||||
/* If hsz2 is a not found, return hsz2 is "zero string".
|
||||
*/
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
LPSTR psz1, psz2;
|
||||
psz1 = HEAP_strdupWtoA( GetProcessHeap(), 0, pwsz1 );
|
||||
psz2 = HEAP_strdupWtoA( GetProcessHeap(), 0, pwsz2 );
|
||||
if( psz1 != NULL && psz2 != NULL )
|
||||
{
|
||||
/* Compare the two strings we got ( case insensitive ).
|
||||
*/
|
||||
ret = strcasecmp( psz1, psz2 );
|
||||
/* Since strcmp returns any number smaller than
|
||||
* 0 when the first string is found to be less than
|
||||
* the second one we must make sure we are returning
|
||||
* the proper values.
|
||||
*/
|
||||
if( ret < 0 )
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
else if( ret > 0 )
|
||||
{
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, psz1 );
|
||||
HeapFree( GetProcessHeap(), 0, psz2 );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ init MAIN_UserInit
|
|||
88 stdcall DdeAccessData(long ptr) DdeAccessData32
|
||||
89 stub DdeAddData
|
||||
90 stdcall DdeClientTransaction(ptr long long long long long long ptr) DdeClientTransaction32
|
||||
91 stdcall DdeCmpStringHandles(long long) DdeCmpStringHandles32
|
||||
91 stdcall DdeCmpStringHandlesA(long long) DdeCmpStringHandles32A
|
||||
92 stdcall DdeConnect(long long long ptr) DdeConnect32
|
||||
93 stdcall DdeConnectList(long long long long ptr) DdeConnectList32
|
||||
94 stdcall DdeCreateDataHandle(long ptr long long long long long) DdeCreateDataHandle32
|
||||
|
@ -615,7 +615,6 @@ init MAIN_UserInit
|
|||
610 stdcall MonitorFromRect(ptr long) MonitorFromRect
|
||||
611 stdcall MonitorFromPoint(long long long) MonitorFromPoint
|
||||
612 stdcall EnumDisplayMonitors(long ptr ptr long) EnumDisplayMonitors
|
||||
|
||||
613 stdcall PrivateExtractIconExA (long long long long long) PrivateExtractIconExA
|
||||
614 stdcall PrivateExtractIconExW (long long long long long) PrivateExtractIconExW
|
||||
615 stdcall PrivateExtractIconsW (long long long long long long long long) PrivateExtractIconsW
|
||||
|
@ -626,3 +625,4 @@ init MAIN_UserInit
|
|||
620 stdcall GetTaskmanWindow () GetTaskmanWindow
|
||||
621 stdcall SetTaskmanWindow (long) SetTaskmanWindow
|
||||
622 stdcall GetProgmanWindow () GetProgmanWindow
|
||||
623 stdcall DdeCmpStringHandlesW(long long) DdeCmpStringHandles32W
|
||||
|
|
Loading…
Reference in New Issue