4 * Copyright 1997 Alexandre Julliard
5 * Copyright 1997 Len White
6 * Copyright 1999 Keith Matthews
9 /* Only empty stubs for now */
18 #include "shm_semaph.h"
22 DEFAULT_DEBUG_CHANNEL(ddeml)
24 /* Has defined in atom.c file.
26 #define MAX_ATOM_LEN 255
28 /* Maximum buffer size ( including the '\0' ).
30 #define MAX_BUFFER_LEN (MAX_ATOM_LEN + 1)
34 LPVOID lpSecurityDescriptor;
36 } SECURITY_ATTRIBUTES; */
38 /* This is a simple list to keep track of the strings created
39 * by DdeCreateStringHandle. The list is used to free
40 * the strings whenever DdeUninitialize is called.
41 * This mechanism is not complete and does not handle multiple instances.
42 * Most of the DDE API use a DWORD parameter indicating which instance
43 * of a given program is calling them. The API are supposed to
44 * associate the data to the instance that created it.
46 typedef struct tagHSZNode HSZNode;
54 typedef struct DDE_HANDLE_ENTRY {
55 BOOL16 Monitor; /* have these two as full Booleans cos they'll be tested frequently */
56 BOOL16 Client_only; /* bit wasteful of space but it will be faster */
57 BOOL16 Unicode; /* Flag to indicate Win32 API used to initialise */
58 BOOL16 Win16; /* flag to indicate Win16 API used to initialize */
59 DWORD Instance_id; /* needed to track monitor usage */
60 struct DDE_HANDLE_ENTRY *Next_Entry;
65 UINT Txn_count; /* count transactions open to simplify closure */
69 static DDE_HANDLE_ENTRY *DDE_Handle_Table_Base = NULL;
70 static DWORD DDE_Max_Assigned_Instance = 0; /* OK for present, may have to worry about wrap-around later */
71 static const char inst_string[]= "DDEMaxInstance";
72 static LPCWSTR DDEInstanceAccess = (LPCWSTR)&inst_string;
73 static const char handle_string[] = "DDEHandleAccess";
74 static LPCWSTR DDEHandleAccess = (LPCWSTR)&handle_string;
75 static HANDLE inst_count_mutex = 0;
76 static HANDLE handle_mutex = 0;
77 DDE_HANDLE_ENTRY *this_instance;
78 SECURITY_ATTRIBUTES *s_att= NULL;
81 DDE_HANDLE_ENTRY *reference_inst;
87 /******************************************************************************
88 * RemoveHSZNodes (INTERNAL)
90 * Remove a node from the list of HSZ nodes.
92 ******************************************************************************
96 * Vn Date Author Comment
98 * 1.0 Dec 1998 Corel/Macadamian Initial version
99 * 1.1 Mar 1999 Keith Matthews Added multiple instance handling
102 static void RemoveHSZNode( HSZ hsz )
104 HSZNode* pPrev = NULL;
105 HSZNode* pCurrent = NULL;
107 /* Set the current node at the start of the list.
109 pCurrent = reference_inst->Node_list;
110 /* While we have more nodes.
112 while( pCurrent != NULL )
114 /* If we found the node we were looking for.
116 if( pCurrent->hsz == hsz )
120 /* If the first node in the list is to to be removed.
121 * Set the global list pointer to the next node.
123 if( pCurrent == reference_inst->Node_list )
125 reference_inst->Node_list = pCurrent->next;
127 /* Just fix the pointers has to skip the current
128 * node so we can delete it.
132 pPrev->next = pCurrent->next;
134 /* Destroy this node.
139 /* Save the previous node pointer.
142 /* Move on to the next node.
144 pCurrent = pCurrent->next;
148 /******************************************************************************
149 * FreeAndRemoveHSZNodes (INTERNAL)
151 * Frees up all the strings still allocated in the list and
152 * remove all the nodes from the list of HSZ nodes.
154 ******************************************************************************
158 * Vn Date Author Comment
160 * 1.0 Dec 1998 Corel/Macadamian Initial version
161 * 1.1 Mar 1999 Keith Matthews Added multiple instance handling
164 static void FreeAndRemoveHSZNodes( DWORD idInst )
166 /* Free any strings created in this instance.
168 while( reference_inst->Node_list != NULL )
170 DdeFreeStringHandle( idInst, reference_inst->Node_list->hsz );
174 /******************************************************************************
175 * InsertHSZNode (INTERNAL)
177 * Insert a node to the head of the list.
179 ******************************************************************************
183 * Vn Date Author Comment
185 * 1.0 Dec 1998 Corel/Macadamian Initial version
186 * 1.1 Mar 1999 Keith Matthews Added instance handling
189 static void InsertHSZNode( HSZ hsz )
193 HSZNode* pNew = NULL;
194 /* Create a new node for this HSZ.
196 pNew = (HSZNode*) malloc( sizeof( HSZNode ) );
199 /* Set the handle value.
202 /* Attach the node to the head of the list. i.e most recently added is first
204 pNew->next = reference_inst->Node_list;
205 /* The new node is now at the head of the list
206 * so set the global list pointer to it.
208 reference_inst->Node_list = pNew;
209 TRACE(ddeml,"HSZ node list entry added\n");
214 /*****************************************************************************
215 * Find_Instance_Entry
217 * generic routine to return a pointer to the relevant DDE_HANDLE_ENTRY
218 * for an instance Id, or NULL if the entry does not exist
220 * ASSUMES the mutex protecting the handle entry list is reserved before calling
222 ******************************************************************************
226 * Vn Date Author Comment
228 * 1.0 March 1999 Keith Matthews 1st implementation
230 DDE_HANDLE_ENTRY *Find_Instance_Entry (DWORD InstId)
232 reference_inst = DDE_Handle_Table_Base;
233 while ( reference_inst != NULL )
235 if ( reference_inst->Instance_id == InstId )
237 TRACE(ddeml,"Instance entry found\n");
238 return reference_inst;
240 reference_inst = reference_inst->Next_Entry;
242 TRACE(ddeml,"Instance entry missing\n");
246 /******************************************************************************
247 * Release_reserved_mutex
249 * generic routine to release a reserved mutex
252 ******************************************************************************
256 * Vn Date Author Comment
258 * 1.0 Jan 1999 Keith Matthews Initial version
259 * 1.1 Mar 1999 Keith Matthews Corrected Heap handling. Corrected re-initialisation handling
262 DWORD Release_reserved_mutex (HANDLE mutex, LPTSTR mutex_name, BOOL release_handle_m, BOOL release_this_i )
265 if ( (err_no=GetLastError()) != 0 )
267 ERR(ddeml,"ReleaseMutex failed - %s mutex %li\n",mutex_name,err_no);
268 HeapFree(SystemHeap, 0, this_instance);
269 if ( release_handle_m )
271 ReleaseMutex(handle_mutex);
273 return DMLERR_SYS_ERROR;
275 if ( release_this_i )
277 HeapFree(SystemHeap, 0, this_instance);
279 return DMLERR_NO_ERROR;
282 /******************************************************************************
283 * IncrementInstanceId
285 * generic routine to increment the max instance Id and allocate a new application instance
287 ******************************************************************************
291 * Vn Date Author Comment
293 * 1.0 Jan 1999 Keith Matthews Initial version
296 DWORD IncrementInstanceId()
298 SECURITY_ATTRIBUTES s_attrib;
299 /* Need to set up Mutex in case it is not already present */
300 /* increment handle count & get value */
301 if ( !inst_count_mutex )
303 s_attrib.bInheritHandle = TRUE;
304 s_attrib.lpSecurityDescriptor = NULL;
305 s_attrib.nLength = sizeof(s_attrib);
306 inst_count_mutex = CreateMutexW(&s_attrib,1,DDEInstanceAccess); /* 1st time through */
308 WaitForSingleObject(inst_count_mutex,1000); /* subsequent calls */
309 /* FIXME - needs refinement with popup for timeout, also is timeout interval OK */
311 if ( (err_no=GetLastError()) != 0 )
313 ERR(ddeml,"CreateMutex failed - inst_count %li\n",err_no);
314 err_no=Release_reserved_mutex (handle_mutex,"handle_mutex",0,1);
315 return DMLERR_SYS_ERROR;
317 DDE_Max_Assigned_Instance++;
318 this_instance->Instance_id = DDE_Max_Assigned_Instance;
319 TRACE(ddeml,"New instance id %ld allocated\n",DDE_Max_Assigned_Instance);
320 if (Release_reserved_mutex(inst_count_mutex,"instance_count",1,0)) return DMLERR_SYS_ERROR;
321 return DMLERR_NO_ERROR;
324 /******************************************************************************
325 * DdeInitialize16 (DDEML.2)
327 UINT16 WINAPI DdeInitialize16( LPDWORD pidInst, PFNCALLBACK16 pfnCallback,
328 DWORD afCmd, DWORD ulRes)
330 TRACE(ddeml,"DdeInitialize16 called - calling DdeInitializeA\n");
331 return (UINT16)DdeInitializeA(pidInst,(PFNCALLBACK)pfnCallback,
336 /******************************************************************************
337 * DdeInitializeA (USER32.106)
339 UINT WINAPI DdeInitializeA( LPDWORD pidInst, PFNCALLBACK pfnCallback,
340 DWORD afCmd, DWORD ulRes )
342 TRACE(ddeml,"DdeInitializeA called - calling DdeInitializeW\n");
343 return DdeInitializeW(pidInst,pfnCallback,afCmd,ulRes);
347 /******************************************************************************
348 * DdeInitializeW [USER32.107]
349 * Registers an application with the DDEML
352 * pidInst [I] Pointer to instance identifier
353 * pfnCallback [I] Pointer to callback function
354 * afCmd [I] Set of command and filter flags
358 * Success: DMLERR_NO_ERROR
359 * Failure: DMLERR_DLL_USAGE, DMLERR_INVALIDPARAMETER, DMLERR_SYS_ERROR
361 ******************************************************************************
365 * Vn Date Author Comment
367 * 1.0 Pre 1998 Alexandre/Len Initial Stub
368 * 1.1 Jan 1999 Keith Matthews Initial (near-)complete version
369 * 1.2 Mar 1999 Keith Matthews Corrected Heap handling, CreateMutex failure handling
372 UINT WINAPI DdeInitializeW( LPDWORD pidInst, PFNCALLBACK pfnCallback,
373 DWORD afCmd, DWORD ulRes )
376 /* probably not really capable of handling mutliple processes, but should handle
377 * multiple instances within one process */
379 SECURITY_ATTRIBUTES s_attrib;
384 ERR(ddeml, "Reserved value not zero? What does this mean?\n");
385 FIXME(ddeml, "(%p,%p,0x%lx,%ld): stub\n", pidInst, pfnCallback,
387 /* trap this and no more until we know more */
388 return DMLERR_NO_ERROR;
392 /* this one may be wrong - MS dll seems to accept the condition,
393 leave this until we find out more !! */
396 /* can't set up the instance with nothing to act as a callback */
397 TRACE(ddeml,"No callback provided\n");
398 return DMLERR_INVALIDPARAMETER; /* might be DMLERR_DLL_USAGE */
401 /* grab enough heap for one control struct - not really necessary for re-initialise
402 * but allows us to use same validation routines */
403 this_instance= (DDE_HANDLE_ENTRY*)HeapAlloc( SystemHeap, 0, sizeof(DDE_HANDLE_ENTRY) );
404 if ( this_instance == NULL )
406 /* catastrophe !! warn user & abort */
407 ERR (ddeml, "Instance create failed - out of memory\n");
408 return DMLERR_SYS_ERROR;
410 this_instance->Next_Entry = NULL;
411 this_instance->Monitor=(afCmd|APPCLASS_MONITOR);
413 /* messy bit, spec implies that 'Client Only' can be set in 2 different ways, catch 1 here */
415 this_instance->Client_only=afCmd&APPCMD_CLIENTONLY;
416 this_instance->Instance_id = *pidInst; /* May need to add calling proc Id */
417 this_instance->CallBack=*pfnCallback;
418 this_instance->Txn_count=0;
419 this_instance->Unicode = TRUE;
420 this_instance->Win16 = FALSE;
421 this_instance->Node_list = NULL; /* node will be added later */
422 this_instance->Monitor_flags = afCmd & MF_MASK;
424 /* isolate CBF flags in one go, expect this will go the way of all attempts to be clever !! */
426 this_instance->CBF_Flags=afCmd^((afCmd&MF_MASK)|((afCmd&APPCMD_MASK)|(afCmd&APPCLASS_MASK)));
428 if ( ! this_instance->Client_only )
431 /* Check for other way of setting Client-only !! */
433 this_instance->Client_only=(this_instance->CBF_Flags&CBF_FAIL_ALLSVRXACTIONS)
434 ==CBF_FAIL_ALLSVRXACTIONS;
437 TRACE(ddeml,"instance created - checking validity \n");
439 if( *pidInst == 0 ) {
440 /* Initialisation of new Instance Identifier */
441 TRACE(ddeml,"new instance, callback %p flags %lX\n",pfnCallback,afCmd);
442 if ( DDE_Max_Assigned_Instance == 0 )
444 /* Nothing has been initialised - exit now ! can return TRUE since effect is the same */
445 /* Need to set up Mutex in case it is not already present */
446 s_att->bInheritHandle = TRUE;
447 s_att->lpSecurityDescriptor = NULL;
448 s_att->nLength = sizeof(s_att);
449 handle_mutex = CreateMutexW(s_att,1,DDEHandleAccess);
450 if ( (err_no=GetLastError()) != 0 )
452 ERR(ddeml,"CreateMutex failed - handle list %li\n",err_no);
453 HeapFree(SystemHeap, 0, this_instance);
454 return DMLERR_SYS_ERROR;
458 WaitForSingleObject(handle_mutex,1000);
459 if ( (err_no=GetLastError()) != 0 )
461 /* FIXME - needs refinement with popup for timeout, also is timeout interval OK */
463 ERR(ddeml,"WaitForSingleObject failed - handle list %li\n",err_no);
464 return DMLERR_SYS_ERROR;
468 TRACE(ddeml,"Handle Mutex created/reserved\n");
469 if (DDE_Handle_Table_Base == NULL )
471 /* can't be another instance in this case, assign to the base pointer */
472 DDE_Handle_Table_Base= this_instance;
474 /* since first must force filter of XTYP_CONNECT and XTYP_WILDCONNECT for
476 * ------------------------------- NOTE NOTE NOTE --------------------------
478 * the manual is not clear if this condition
479 * applies to the first call to DdeInitialize from an application, or the
480 * first call for a given callback !!!
483 this_instance->CBF_Flags=this_instance->CBF_Flags|APPCMD_FILTERINITS;
484 TRACE(ddeml,"First application instance detected OK\n");
485 /* allocate new instance ID */
486 if ((err_no = IncrementInstanceId()) ) return err_no;
488 /* really need to chain the new one in to the latest here, but after checking conditions
489 * such as trying to start a conversation from an application trying to monitor */
490 reference_inst = DDE_Handle_Table_Base;
491 TRACE(ddeml,"Subsequent application instance - starting checks\n");
492 while ( reference_inst->Next_Entry != NULL )
495 * This set of tests will work if application uses same instance Id
496 * at application level once allocated - which is what manual implies
497 * should happen. If someone tries to be
498 * clever (lazy ?) it will fail to pick up that later calls are for
499 * the same application - should we trust them ?
501 if ( this_instance->Instance_id == reference_inst->Instance_id)
503 /* Check 1 - must be same Client-only state */
505 if ( this_instance->Client_only != reference_inst->Client_only)
507 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,1))
508 return DMLERR_SYS_ERROR;
509 return DMLERR_DLL_USAGE;
512 /* Check 2 - cannot use 'Monitor' with any non-monitor modes */
514 if ( this_instance->Monitor != reference_inst->Monitor)
516 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,1))
517 return DMLERR_SYS_ERROR;
518 return DMLERR_INVALIDPARAMETER;
521 /* Check 3 - must supply different callback address */
523 if ( this_instance->CallBack == reference_inst->CallBack)
525 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,1))
526 return DMLERR_SYS_ERROR;
527 return DMLERR_DLL_USAGE;
530 reference_inst = reference_inst->Next_Entry;
532 /* All cleared, add to chain */
534 TRACE(ddeml,"Application Instance checks finished\n");
535 if ((err_no = IncrementInstanceId())) return err_no;
536 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,0)) return DMLERR_SYS_ERROR;
537 reference_inst->Next_Entry = this_instance;
539 *pidInst = this_instance->Instance_id;
540 TRACE(ddeml,"New application instance processing finished OK\n");
542 /* Reinitialisation situation --- FIX */
543 TRACE(ddeml,"reinitialisation of (%p,%p,0x%lx,%ld): stub\n",pidInst,pfnCallback,afCmd,ulRes);
544 WaitForSingleObject(handle_mutex,1000);
545 if ( (err_no=GetLastError()) != 0 )
548 /* FIXME - needs refinement with popup for timeout, also is timeout interval OK */
550 ERR(ddeml,"WaitForSingleObject failed - handle list %li\n",err_no);
551 HeapFree(SystemHeap, 0, this_instance);
552 return DMLERR_SYS_ERROR;
554 if (DDE_Handle_Table_Base == NULL )
556 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,1)) return DMLERR_SYS_ERROR;
557 return DMLERR_DLL_USAGE;
559 HeapFree(SystemHeap, 0, this_instance); /* finished - release heap space used as work store */
560 /* can't reinitialise if we have initialised nothing !! */
561 reference_inst = DDE_Handle_Table_Base;
562 /* must first check if we have been given a valid instance to re-initialise !! how do we do that ? */
564 * MS allows initialisation without specifying a callback, should we allow addition of the
565 * callback by a later call to initialise ? - if so this lot will have to change
567 while ( reference_inst->Next_Entry != NULL )
569 if ( *pidInst == reference_inst->Instance_id && pfnCallback == reference_inst->CallBack )
571 /* Check 1 - cannot change client-only mode if set via APPCMD_CLIENTONLY */
573 if ( reference_inst->Client_only )
575 if ((reference_inst->CBF_Flags & CBF_FAIL_ALLSVRXACTIONS) != CBF_FAIL_ALLSVRXACTIONS)
577 /* i.e. Was set to Client-only and through APPCMD_CLIENTONLY */
579 if ( ! ( afCmd & APPCMD_CLIENTONLY))
581 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,1))
582 return DMLERR_SYS_ERROR;
583 return DMLERR_DLL_USAGE;
587 /* Check 2 - cannot change monitor modes */
589 if ( this_instance->Monitor != reference_inst->Monitor)
591 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,1))
592 return DMLERR_SYS_ERROR;
593 return DMLERR_DLL_USAGE;
596 /* Check 3 - trying to set Client-only via APPCMD when not set so previously */
598 if (( afCmd&APPCMD_CLIENTONLY) && ! reference_inst->Client_only )
600 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,1))
601 return DMLERR_SYS_ERROR;
602 return DMLERR_DLL_USAGE;
606 reference_inst = reference_inst->Next_Entry;
608 if ( reference_inst->Next_Entry == NULL )
610 /* Crazy situation - trying to re-initialize something that has not beeen initialized !!
612 * Manual does not say what we do, cannot return DMLERR_NOT_INITIALIZED so what ?
614 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,1))
615 return DMLERR_SYS_ERROR;
616 return DMLERR_INVALIDPARAMETER;
618 /* All checked - change relevant flags */
620 reference_inst->CBF_Flags = this_instance->CBF_Flags;
621 reference_inst->Client_only = this_instance->Client_only;
622 reference_inst->Monitor_flags = this_instance->Monitor_flags;
623 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,1))
624 return DMLERR_SYS_ERROR;
627 return DMLERR_NO_ERROR;
631 /*****************************************************************
632 * DdeUninitialize16 (DDEML.3)
634 BOOL16 WINAPI DdeUninitialize16( DWORD idInst )
636 FIXME(ddeml," stub calling DdeUninitialize\n");
637 return (BOOL16)DdeUninitialize( idInst );
641 /*****************************************************************
642 * DdeUninitialize [USER32.119] Frees DDEML resources
645 * idInst [I] Instance identifier
652 BOOL WINAPI DdeUninitialize( DWORD idInst )
654 /* Stage one - check if we have a handle for this instance
656 SECURITY_ATTRIBUTES s_attrib;
659 if ( DDE_Max_Assigned_Instance == 0 )
661 /* Nothing has been initialised - exit now ! can return TRUE since effect is the same */
664 WaitForSingleObject(handle_mutex,1000);
665 if ( (err_no=GetLastError()) != 0 )
667 /* FIXME - needs refinement with popup for timeout, also is timeout interval OK */
669 ERR(ddeml,"WaitForSingleObject failed - handle list %li\n",err_no);
670 return DMLERR_SYS_ERROR;
672 TRACE(ddeml,"Handle Mutex created/reserved\n");
673 /* First check instance
675 this_instance = Find_Instance_Entry(idInst);
676 if ( this_instance == NULL )
678 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",FALSE,FALSE)) return FALSE;
680 * Needs something here to record NOT_INITIALIZED ready for DdeGetLastError
684 FIXME(ddeml, "(%ld): partial stub\n", idInst);
686 /* Free the nodes that were not freed by this instance
687 * and remove the nodes from the list of HSZ nodes.
689 FreeAndRemoveHSZNodes( idInst );
691 /* OK now delete the instance handle itself */
693 if ( DDE_Handle_Table_Base == this_instance )
695 /* special case - the first/only entry
697 DDE_Handle_Table_Base = this_instance->Next_Entry;
702 reference_inst->Next_Entry = DDE_Handle_Table_Base;
703 while ( reference_inst->Next_Entry != this_instance )
705 reference_inst = this_instance->Next_Entry;
707 reference_inst->Next_Entry = this_instance->Next_Entry;
709 /* release the mutex and the heap entry
711 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",FALSE,TRUE))
713 /* should record something here, but nothing left to hang it from !!
721 /*****************************************************************
722 * DdeConnectList16 [DDEML.4]
725 HCONVLIST WINAPI DdeConnectList16( DWORD idInst, HSZ hszService, HSZ hszTopic,
726 HCONVLIST hConvList, LPCONVCONTEXT16 pCC )
728 return DdeConnectList(idInst, hszService, hszTopic, hConvList,
733 /******************************************************************************
734 * DdeConnectList [USER32.93] Establishes conversation with DDE servers
737 * idInst [I] Instance identifier
738 * hszService [I] Handle to service name string
739 * hszTopic [I] Handle to topic name string
740 * hConvList [I] Handle to conversation list
741 * pCC [I] Pointer to structure with context data
744 * Success: Handle to new conversation list
747 HCONVLIST WINAPI DdeConnectList( DWORD idInst, HSZ hszService, HSZ hszTopic,
748 HCONVLIST hConvList, LPCONVCONTEXT pCC )
750 FIXME(ddeml, "(%ld,%ld,%ld,%ld,%p): stub\n", idInst, hszService, hszTopic,
756 /*****************************************************************
757 * DdeQueryNextServer16 [DDEML.5]
759 HCONV WINAPI DdeQueryNextServer16( HCONVLIST hConvList, HCONV hConvPrev )
761 return DdeQueryNextServer(hConvList, hConvPrev);
765 /*****************************************************************
766 * DdeQueryNextServer [USER32.112]
768 HCONV WINAPI DdeQueryNextServer( HCONVLIST hConvList, HCONV hConvPrev )
770 FIXME(ddeml, "(%ld,%ld): stub\n",hConvList,hConvPrev);
774 /*****************************************************************
775 * DdeQueryStringA [USER32.113]
777 *****************************************************************
781 * Vn Date Author Comment
783 * 1.0 Dec 1998 Corel/Macadamian Initial version
784 * 1.1 Mar 1999 Keith Matthews Added links to instance table and related processing
787 DWORD WINAPI DdeQueryStringA(DWORD idInst, HSZ hsz, LPSTR psz, DWORD cchMax, INT iCodePage)
790 CHAR pString[MAX_BUFFER_LEN];
793 "(%ld, 0x%lx, %p, %ld, %d): partial stub\n",
799 if ( DDE_Max_Assigned_Instance == 0 )
801 /* Nothing has been initialised - exit now ! */
802 /* needs something for DdeGetLAstError even if the manual doesn't say so */
805 WaitForSingleObject(handle_mutex,1000);
806 if ( (err_no=GetLastError()) != 0 )
808 /* FIXME - needs refinement with popup for timeout, also is timeout interval OK */
810 ERR(ddeml,"WaitForSingleObject failed - handle list %li\n",err_no);
811 /* needs something for DdeGetLAstError even if the manual doesn't say so */
814 TRACE(ddeml,"Handle Mutex created/reserved\n");
816 /* First check instance
818 reference_inst = Find_Instance_Entry(idInst);
819 if ( reference_inst == NULL )
821 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",FALSE,FALSE)) return FALSE;
823 Needs something here to record NOT_INITIALIZED ready for DdeGetLastError
828 if( iCodePage == CP_WINANSI )
830 /* If psz is null, we have to return only the length
836 cchMax = MAX_BUFFER_LEN;
839 ret = GlobalGetAtomNameA( hsz, (LPSTR)psz, cchMax );
841 Release_reserved_mutex(handle_mutex,"handle_mutex",FALSE,FALSE);
843 TRACE(ddeml,"returning pointer\n");
847 /*****************************************************************
848 * DdeQueryStringW [USER32.114]
850 *****************************************************************
854 * Vn Date Author Comment
856 * 1.0 Dec 1998 Corel/Macadamian Initial version
860 DWORD WINAPI DdeQueryStringW(DWORD idInst, HSZ hsz, LPWSTR psz, DWORD cchMax, INT iCodePage)
863 WCHAR pString[MAX_BUFFER_LEN];
867 "(%ld, 0x%lx, %p, %ld, %d): stub\n",
874 if( iCodePage == CP_WINUNICODE )
876 /* If psz is null, we have to return only the length
882 cchMax = MAX_BUFFER_LEN;
883 /* Note: According to documentation if the psz parameter
884 * was NULL this API must return the length of the string in bytes.
886 factor = (int) sizeof(WCHAR)/sizeof(BYTE);
888 ret = GlobalGetAtomNameW( hsz, (LPWSTR)psz, cchMax ) * factor;
893 /*****************************************************************
895 * DdeQueryString16 (DDEML.23)
897 ******************************************************************
901 * Vn Date Author Comment
903 * 1.0 March 1999 K Matthews stub only
906 DWORD WINAPI DdeQueryString16(DWORD idInst, HSZ hsz, LPSTR lpsz, DWORD cchMax, int codepage)
908 FIXME(ddeml,"(%ld, 0x%lx, %p, %ld, %d): stub \n",
918 /*****************************************************************
919 * DdeDisconnectList (DDEML.6)
921 BOOL16 WINAPI DdeDisconnectList16( HCONVLIST hConvList )
923 return (BOOL16)DdeDisconnectList(hConvList);
927 /******************************************************************************
928 * DdeDisconnectList [USER32.98] Destroys list and terminates conversations
934 BOOL WINAPI DdeDisconnectList(
935 HCONVLIST hConvList) /* [in] Handle to conversation list */
937 FIXME(ddeml, "(%ld): stub\n", hConvList);
942 /*****************************************************************
943 * DdeConnect16 (DDEML.7)
945 HCONV WINAPI DdeConnect16( DWORD idInst, HSZ hszService, HSZ hszTopic,
946 LPCONVCONTEXT16 pCC )
948 FIXME( ddeml, "empty stub\n" );
953 /*****************************************************************
954 * DdeConnect (USER32.92)
956 HCONV WINAPI DdeConnect( DWORD idInst, HSZ hszService, HSZ hszTopic,
959 FIXME(ddeml, "(0x%lx,%ld,%ld,%p): stub\n",idInst,hszService,hszTopic,
965 /*****************************************************************
966 * DdeDisconnect16 (DDEML.8)
968 BOOL16 WINAPI DdeDisconnect16( HCONV hConv )
970 return (BOOL16)DdeDisconnect( hConv );
973 /*****************************************************************
974 * DdeSetUserHandle16 (DDEML.10)
976 BOOL16 WINAPI DdeSetUserHandle16( HCONV hConv, DWORD id, DWORD hUser )
978 FIXME( ddeml, "(%ld,%ld,%ld): stub\n",hConv,id, hUser );
982 /*****************************************************************
983 * DdeCreateDataHandle16 (DDEML.14)
985 HDDEDATA WINAPI DdeCreateDataHandle16( DWORD idInst, LPBYTE pSrc, DWORD cb,
986 DWORD cbOff, HSZ hszItem, UINT16 wFmt,
989 return DdeCreateDataHandle(idInst,
998 /*****************************************************************
999 * DdeCreateDataHandle (USER32.94)
1001 HDDEDATA WINAPI DdeCreateDataHandle( DWORD idInst, LPBYTE pSrc, DWORD cb,
1002 DWORD cbOff, HSZ hszItem, UINT wFmt,
1006 "(%ld,%p,%ld,%ld,0x%lx,%d,%d): stub\n",
1018 /*****************************************************************
1019 * DdeDisconnect (USER32.97)
1021 BOOL WINAPI DdeDisconnect( HCONV hConv )
1023 FIXME( ddeml, "empty stub\n" );
1028 /*****************************************************************
1029 * DdeReconnect (DDEML.37) (USER32.115)
1031 HCONV WINAPI DdeReconnect( HCONV hConv )
1033 FIXME( ddeml, "empty stub\n" );
1038 /*****************************************************************
1039 * DdeCreateStringHandle16 (DDEML.21)
1041 HSZ WINAPI DdeCreateStringHandle16( DWORD idInst, LPCSTR str, INT16 codepage )
1043 return DdeCreateStringHandleA( idInst, str, codepage );
1047 /*****************************************************************
1048 * DdeCreateStringHandleA [USER32.95]
1051 * Success: String handle
1054 *****************************************************************
1058 * Vn Date Author Comment
1060 * 1.0 Dec 1998 Corel/Macadamian Initial version
1061 * 1.1 Mar 1999 Keith Matthews Added links to instance table and related processing
1064 HSZ WINAPI DdeCreateStringHandleA( DWORD idInst, LPCSTR psz, INT codepage )
1067 TRACE(ddeml, "(%ld,%s,%d): partial stub\n",idInst,debugstr_a(psz),codepage);
1070 if ( DDE_Max_Assigned_Instance == 0 )
1072 /* Nothing has been initialised - exit now ! can return TRUE since effect is the same */
1075 WaitForSingleObject(handle_mutex,1000);
1076 if ( (err_no=GetLastError()) != 0 )
1078 /* FIXME - needs refinement with popup for timeout, also is timeout interval OK */
1080 ERR(ddeml,"WaitForSingleObject failed - handle list %li\n",err_no);
1081 return DMLERR_SYS_ERROR;
1083 TRACE(ddeml,"Handle Mutex created/reserved\n");
1085 /* First check instance
1087 reference_inst = Find_Instance_Entry(idInst);
1088 if ( reference_inst == NULL )
1090 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",FALSE,FALSE)) return 0;
1092 Needs something here to record NOT_INITIALIZED ready for DdeGetLastError
1097 if (codepage==CP_WINANSI)
1099 hsz = GlobalAddAtomA (psz);
1100 /* Save the handle so we know to clean it when
1101 * uninitialize is called.
1103 InsertHSZNode( hsz );
1104 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",FALSE,FALSE))
1106 reference_inst->Last_Error = DMLERR_SYS_ERROR;
1109 TRACE(ddeml,"Returning pointer\n");
1112 Release_reserved_mutex(handle_mutex,"handle_mutex",FALSE,FALSE);
1114 TRACE(ddeml,"Returning error\n");
1119 /******************************************************************************
1120 * DdeCreateStringHandleW [USER32.96] Creates handle to identify string
1123 * Success: String handle
1126 *****************************************************************
1130 * Vn Date Author Comment
1132 * 1.0 Dec 1998 Corel/Macadamian Initial version
1133 * 1.1 Mar 1999 Keith Matthews Added links to instance table and related processing
1136 HSZ WINAPI DdeCreateStringHandleW(
1137 DWORD idInst, /* [in] Instance identifier */
1138 LPCWSTR psz, /* [in] Pointer to string */
1139 INT codepage) /* [in] Code page identifier */
1143 TRACE(ddeml, "(%ld,%s,%d): partial stub\n",idInst,debugstr_w(psz),codepage);
1146 if ( DDE_Max_Assigned_Instance == 0 )
1148 /* Nothing has been initialised - exit now ! can return TRUE since effect is the same */
1151 WaitForSingleObject(handle_mutex,1000);
1152 if ( (err_no=GetLastError()) != 0 )
1154 /* FIXME - needs refinement with popup for timeout, also is timeout interval OK */
1156 ERR(ddeml,"WaitForSingleObject failed - handle list %li\n",err_no);
1157 return DMLERR_SYS_ERROR;
1159 TRACE(ddeml,"CreateString - Handle Mutex created/reserved\n");
1161 /* First check instance
1163 reference_inst = Find_Instance_Entry(idInst);
1164 if ( reference_inst == NULL )
1166 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",FALSE,FALSE)) return 0;
1168 Needs something here to record NOT_INITIALIZED ready for DdeGetLastError
1173 FIXME(ddeml, "(%ld,%s,%d): partial stub\n",idInst,debugstr_w(psz),codepage);
1175 if (codepage==CP_WINUNICODE)
1177 Should we be checking this against the unicode/ascii nature of the call to DdeInitialize ?
1180 hsz = GlobalAddAtomW (psz);
1181 /* Save the handle so we know to clean it when
1182 * uninitialize is called.
1184 InsertHSZNode( hsz );
1185 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",FALSE,FALSE))
1187 reference_inst->Last_Error = DMLERR_SYS_ERROR;
1190 TRACE(ddeml,"Returning pointer\n");
1193 Release_reserved_mutex(handle_mutex,"handle_mutex",FALSE,FALSE);
1195 TRACE(ddeml,"Returning error\n");
1200 /*****************************************************************
1201 * DdeFreeStringHandle16 (DDEML.22)
1203 BOOL16 WINAPI DdeFreeStringHandle16( DWORD idInst, HSZ hsz )
1205 FIXME(ddeml,"idInst %ld hsz 0x%lx\n",idInst,hsz);
1206 return (BOOL)DdeFreeStringHandle( idInst, hsz );
1210 /*****************************************************************
1211 * DdeFreeStringHandle (USER32.101)
1212 * RETURNS: success: nonzero
1215 *****************************************************************
1219 * Vn Date Author Comment
1221 * 1.0 Dec 1998 Corel/Macadamian Initial version
1222 * 1.1 Apr 1999 Keith Matthews Added links to instance table and related processing
1225 BOOL WINAPI DdeFreeStringHandle( DWORD idInst, HSZ hsz )
1227 TRACE(ddeml, "(%ld,%ld): \n",idInst,hsz);
1228 if ( DDE_Max_Assigned_Instance == 0 )
1230 /* Nothing has been initialised - exit now ! can return TRUE since effect is the same */
1233 if ( ( prev_err = GetLastError()) != 0 )
1235 /* something earlier failed !! */
1236 ERR(ddeml,"Error %li before WaitForSingleObject - trying to continue\n",prev_err);
1238 WaitForSingleObject(handle_mutex,1000);
1239 if ( ((err_no=GetLastError()) != 0 ) && (err_no != prev_err ))
1241 /* FIXME - needs refinement with popup for timeout, also is timeout interval OK */
1243 ERR(ddeml,"WaitForSingleObject failed - handle list %li\n",err_no);
1244 return DMLERR_SYS_ERROR;
1246 TRACE(ddeml,"Handle Mutex created/reserved\n");
1248 /* First check instance
1250 reference_inst = Find_Instance_Entry(idInst);
1251 if ( (reference_inst == NULL) | (reference_inst->Node_list == NULL))
1253 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",FALSE,FALSE)) return TRUE;
1254 /* Nothing has been initialised - exit now ! can return TRUE since effect is the same */
1259 /* Remove the node associated with this HSZ.
1261 RemoveHSZNode( hsz );
1262 /* Free the string associated with this HSZ.
1264 Release_reserved_mutex(handle_mutex,"handle_mutex",FALSE,FALSE);
1265 return GlobalDeleteAtom (hsz) ? 0 : hsz;
1269 /*****************************************************************
1270 * DdeFreeDataHandle16 (DDEML.19)
1272 BOOL16 WINAPI DdeFreeDataHandle16( HDDEDATA hData )
1274 return (BOOL)DdeFreeDataHandle( hData );
1278 /*****************************************************************
1279 * DdeFreeDataHandle (USER32.100)
1281 BOOL WINAPI DdeFreeDataHandle( HDDEDATA hData )
1283 FIXME( ddeml, "empty stub\n" );
1290 /*****************************************************************
1291 * DdeKeepStringHandle16 (DDEML.24)
1293 BOOL16 WINAPI DdeKeepStringHandle16( DWORD idInst, HSZ hsz )
1295 return (BOOL)DdeKeepStringHandle( idInst, hsz );
1299 /*****************************************************************
1300 * DdeKeepStringHandle (USER32.108)
1302 BOOL WINAPI DdeKeepStringHandle( DWORD idInst, HSZ hsz )
1304 FIXME( ddeml, "empty stub\n" );
1309 /*****************************************************************
1310 * DdeClientTransaction16 (DDEML.11)
1312 HDDEDATA WINAPI DdeClientTransaction16( LPVOID pData, DWORD cbData,
1313 HCONV hConv, HSZ hszItem, UINT16 wFmt,
1314 UINT16 wType, DWORD dwTimeout,
1317 return DdeClientTransaction( (LPBYTE)pData, cbData, hConv, hszItem,
1318 wFmt, wType, dwTimeout, pdwResult );
1322 /*****************************************************************
1323 * DdeClientTransaction (USER32.90)
1325 HDDEDATA WINAPI DdeClientTransaction( LPBYTE pData, DWORD cbData,
1326 HCONV hConv, HSZ hszItem, UINT wFmt,
1327 UINT wType, DWORD dwTimeout,
1330 FIXME( ddeml, "empty stub\n" );
1334 /*****************************************************************
1336 * DdeAbandonTransaction16 (DDEML.12)
1339 BOOL16 WINAPI DdeAbandonTransaction16( DWORD idInst, HCONV hConv,
1340 DWORD idTransaction )
1342 FIXME( ddeml, "empty stub\n" );
1347 /*****************************************************************
1349 * DdeAbandonTransaction (USER32.87)
1351 ******************************************************************
1355 * Vn Date Author Comment
1357 * 1.0 March 1999 K Matthews stub only
1359 BOOL WINAPI DdeAbandonTransaction( DWORD idInst, HCONV hConv,
1360 DWORD idTransaction )
1362 FIXME( ddeml, "empty stub\n" );
1366 /*****************************************************************
1367 * DdePostAdvise16 [DDEML.13]
1369 BOOL16 WINAPI DdePostAdvise16( DWORD idInst, HSZ hszTopic, HSZ hszItem )
1371 return (BOOL16)DdePostAdvise(idInst, hszTopic, hszItem);
1375 /******************************************************************************
1376 * DdePostAdvise [USER32.110] Send transaction to DDE callback function.
1382 BOOL WINAPI DdePostAdvise(
1383 DWORD idInst, /* [in] Instance identifier */
1384 HSZ hszTopic, /* [in] Handle to topic name string */
1385 HSZ hszItem) /* [in] Handle to item name string */
1387 FIXME(ddeml, "(%ld,%ld,%ld): stub\n",idInst,hszTopic,hszItem);
1392 /*****************************************************************
1393 * DdeAddData16 (DDEML.15)
1395 HDDEDATA WINAPI DdeAddData16( HDDEDATA hData, LPBYTE pSrc, DWORD cb,
1398 FIXME( ddeml, "empty stub\n" );
1402 /*****************************************************************
1404 * DdeAddData (USER32.89)
1406 ******************************************************************
1410 * Vn Date Author Comment
1412 * 1.0 March 1999 K Matthews stub only
1414 HDDEDATA WINAPI DdeAddData( HDDEDATA hData, LPBYTE pSrc, DWORD cb,
1417 FIXME( ddeml, "empty stub\n" );
1422 /*****************************************************************
1424 * DdeImpersonateClient (USER32.105)
1426 ******************************************************************
1430 * Vn Date Author Comment
1432 * 1.0 March 1999 K Matthews stub only
1435 BOOL WINAPI DdeImpersonateClient( HCONV hConv)
1437 FIXME( ddeml, "empty stub\n" );
1442 /*****************************************************************
1444 * DdeSetQualityOfService (USER32.116)
1446 ******************************************************************
1450 * Vn Date Author Comment
1452 * 1.0 March 1999 K Matthews stub only
1455 BOOL WINAPI DdeSetQualityOfService( HWND hwndClient, CONST SECURITY_QUALITY_OF_SERVICE *pqosNew,
1456 PSECURITY_QUALITY_OF_SERVICE pqosPrev)
1458 FIXME( ddeml, "empty stub\n" );
1462 /*****************************************************************
1464 * DdeSetUserHandle (USER32.117)
1466 ******************************************************************
1470 * Vn Date Author Comment
1472 * 1.0 March 1999 K Matthews stub only
1475 BOOL WINAPI DdeSetUserHandle( HCONV hConv, DWORD id, DWORD hUser)
1477 FIXME( ddeml, "empty stub\n" );
1481 /******************************************************************************
1482 * DdeGetData [USER32.102] Copies data from DDE object ot local buffer
1485 * Size of memory object associated with handle
1487 DWORD WINAPI DdeGetData(
1488 HDDEDATA hData, /* [in] Handle to DDE object */
1489 LPBYTE pDst, /* [in] Pointer to destination buffer */
1490 DWORD cbMax, /* [in] Amount of data to copy */
1491 DWORD cbOff) /* [in] Offset to beginning of data */
1493 FIXME(ddeml, "(%ld,%p,%ld,%ld): stub\n",hData,pDst,cbMax,cbOff);
1498 /*****************************************************************
1499 * DdeGetData16 [DDEML.16]
1501 DWORD WINAPI DdeGetData16(
1507 return DdeGetData(hData, pDst, cbMax, cbOff);
1511 /*****************************************************************
1512 * DdeAccessData16 (DDEML.17)
1514 LPBYTE WINAPI DdeAccessData16( HDDEDATA hData, LPDWORD pcbDataSize )
1516 return DdeAccessData(hData, pcbDataSize);
1519 /*****************************************************************
1520 * DdeAccessData (USER32.88)
1522 LPBYTE WINAPI DdeAccessData( HDDEDATA hData, LPDWORD pcbDataSize )
1524 FIXME( ddeml, "(%ld,%p): stub\n", hData, pcbDataSize);
1528 /*****************************************************************
1529 * DdeUnaccessData16 (DDEML.18)
1531 BOOL16 WINAPI DdeUnaccessData16( HDDEDATA hData )
1533 return DdeUnaccessData(hData);
1536 /*****************************************************************
1537 * DdeUnaccessData (USER32.118)
1539 BOOL WINAPI DdeUnaccessData( HDDEDATA hData )
1541 FIXME( ddeml, "(0x%lx): stub\n", hData);
1546 /*****************************************************************
1547 * DdeEnableCallback16 (DDEML.26)
1549 BOOL16 WINAPI DdeEnableCallback16( DWORD idInst, HCONV hConv, UINT16 wCmd )
1551 return DdeEnableCallback(idInst, hConv, wCmd);
1554 /*****************************************************************
1555 * DdeEnableCallback (USER32.99)
1557 BOOL WINAPI DdeEnableCallback( DWORD idInst, HCONV hConv, UINT wCmd )
1559 FIXME( ddeml, "(%ld, 0x%lx, %d) stub\n", idInst, hConv, wCmd);
1564 /*****************************************************************
1565 * DdeNameService16 (DDEML.27)
1567 HDDEDATA WINAPI DdeNameService16( DWORD idInst, HSZ hsz1, HSZ hsz2,
1570 return DdeNameService( idInst, hsz1, hsz2, afCmd );
1574 /******************************************************************************
1575 * DdeNameService [USER32.109] {Un}registers service name of DDE server
1578 * idInst [I] Instance identifier
1579 * hsz1 [I] Handle to service name string
1581 * afCmd [I] Service name flags
1587 *****************************************************************
1591 * Vn Date Author Comment
1594 * 1.1 Apr 1999 Keith Matthews Added trap for non-existent instance (uninitialised instance 0
1595 * used by some MS programs for unfathomable reasons)
1598 HDDEDATA WINAPI DdeNameService( DWORD idInst, HSZ hsz1, HSZ hsz2,
1601 FIXME(ddeml, "(%ld,%ld,%ld,%d): stub\n",idInst,hsz1,hsz2,afCmd);
1602 if ( DDE_Max_Assigned_Instance == 0 )
1604 /* Nothing has been initialised - exit now !
1605 * needs something for DdeGetLastError */
1612 /*****************************************************************
1613 * DdeGetLastError16 (DDEML.20)
1615 UINT16 WINAPI DdeGetLastError16( DWORD idInst )
1617 return (UINT16)DdeGetLastError( idInst );
1621 /******************************************************************************
1622 * DdeGetLastError [USER32.103] Gets most recent error code
1625 * idInst [I] Instance identifier
1630 *****************************************************************
1634 * Vn Date Author Comment
1637 * 1.1 Apr 1999 Keith Matthews Added response for non-existent instance (uninitialised instance 0
1638 * used by some MS programs for unfathomable reasons)
1641 UINT WINAPI DdeGetLastError( DWORD idInst )
1643 FIXME(ddeml, "(%ld): stub\n",idInst);
1644 if ( DDE_Max_Assigned_Instance == 0 )
1646 /* Nothing has been initialised - exit now ! */
1647 return DMLERR_DLL_NOT_INITIALIZED;
1649 if ( ( prev_err = GetLastError()) != 0 )
1651 /* something earlier failed !! */
1652 ERR(ddeml,"Error %li before WaitForSingleObject - trying to continue\n",prev_err);
1654 WaitForSingleObject(handle_mutex,1000);
1655 if ( ((err_no=GetLastError()) != 0 ) && (err_no != prev_err ))
1657 /* FIXME - needs refinement with popup for timeout, also is timeout interval OK */
1659 ERR(ddeml,"WaitForSingleObject failed - handle list %li\n",err_no);
1660 return DMLERR_SYS_ERROR;
1662 TRACE(ddeml,"Handle Mutex created/reserved\n");
1664 /* First check instance
1666 reference_inst = Find_Instance_Entry(idInst);
1667 if (reference_inst == NULL)
1669 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",FALSE,FALSE)) return TRUE;
1670 /* Nothing has been initialised - exit now ! can return TRUE since effect is the same */
1671 return DMLERR_DLL_NOT_INITIALIZED;
1676 Release_reserved_mutex(handle_mutex,"handle_mutex",FALSE,FALSE);
1681 /*****************************************************************
1682 * DdeCmpStringHandles16 (DDEML.36)
1684 int WINAPI DdeCmpStringHandles16( HSZ hsz1, HSZ hsz2 )
1686 return DdeCmpStringHandles(hsz1, hsz2);
1689 /*****************************************************************
1690 * DdeCmpStringHandles (USER32.91)
1692 * Compares the value of two string handles. This comparison is
1693 * not case sensitive.
1696 * -1 The value of hsz1 is zero or less than hsz2
1697 * 0 The values of hsz 1 and 2 are the same or both zero.
1698 * 1 The value of hsz2 is zero of less than hsz1
1700 int WINAPI DdeCmpStringHandles( HSZ hsz1, HSZ hsz2 )
1702 CHAR psz1[MAX_BUFFER_LEN];
1703 CHAR psz2[MAX_BUFFER_LEN];
1707 TRACE( ddeml, "handle 1, handle 2\n" );
1709 ret1 = GlobalGetAtomNameA( hsz1, psz1, MAX_BUFFER_LEN );
1710 ret2 = GlobalGetAtomNameA( hsz2, psz2, MAX_BUFFER_LEN );
1711 /* Make sure we found both strings.
1713 if( ret1 == 0 && ret2 == 0 )
1715 /* If both are not found, return both "zero strings".
1719 else if( ret1 == 0 )
1721 /* If hsz1 is a not found, return hsz1 is "zero string".
1725 else if( ret2 == 0 )
1727 /* If hsz2 is a not found, return hsz2 is "zero string".
1733 /* Compare the two strings we got ( case insensitive ).
1735 ret = strcasecmp( psz1, psz2 );
1736 /* Since strcmp returns any number smaller than
1737 * 0 when the first string is found to be less than
1738 * the second one we must make sure we are returning
1739 * the proper values.
1754 /*****************************************************************
1755 * PackDDElParam (USER32.414)
1761 UINT WINAPI PackDDElParam(UINT msg, UINT uiLo, UINT uiHi)
1763 FIXME(ddeml, "stub.\n");
1768 /*****************************************************************
1769 * UnpackDDElParam (USER32.562)
1775 UINT WINAPI UnpackDDElParam(UINT msg, UINT lParam,
1776 UINT *uiLo, UINT *uiHi)
1778 FIXME(ddeml, "stub.\n");
1783 /*****************************************************************
1784 * FreeDDElParam (USER32.204)
1790 UINT WINAPI FreeDDElParam(UINT msg, UINT lParam)
1792 FIXME(ddeml, "stub.\n");
1796 /*****************************************************************
1797 * ReuseDDElParam (USER32.446)
1800 UINT WINAPI ReuseDDElParam(UINT lParam, UINT msgIn, UINT msgOut,
1801 UINT uiLi, UINT uiHi)
1803 FIXME(ddeml, "stub.\n");
1807 /******************************************************************
1808 * DdeQueryConvInfo16 (DDEML.9)
1811 UINT16 WINAPI DdeQueryConvInfo16( HCONV hconv, DWORD idTransaction , LPCONVINFO16 lpConvInfo)
1813 FIXME(ddeml,"stub.\n");
1818 /******************************************************************
1819 * DdeQueryConvInfo (USER32.111)
1822 UINT WINAPI DdeQueryConvInfo( HCONV hconv, DWORD idTransaction , LPCONVINFO lpConvInfo)
1824 FIXME(ddeml,"stub.\n");