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"
21 /* Has defined in atom.c file.
23 #define MAX_ATOM_LEN 255
25 /* Maximum buffer size ( including the '\0' ).
27 #define MAX_BUFFER_LEN (MAX_ATOM_LEN + 1)
30 static DDE_HANDLE_ENTRY *DDE_Handle_Table_Base = NULL;
31 static LPDWORD DDE_Max_Assigned_Instance = 0; // OK for present, may have to worry about wrap-around later
32 static const char inst_string[]= "DDEMaxInstance";
33 static LPCWSTR DDEInstanceAccess = (LPCWSTR)&inst_string;
34 static const char handle_string[] = "DDEHandleAccess";
35 static LPCWSTR DDEHandleAccess = (LPCWSTR)&handle_string;
36 static HANDLE32 inst_count_mutex = 0;
37 static HANDLE32 handle_mutex = 0;
38 DDE_HANDLE_ENTRY *this_instance;
39 SECURITY_ATTRIBUTES *s_att= NULL;
44 LPVOID lpSecurityDescriptor;
45 BOOL32 bInheritHandle;
46 } SECURITY_ATTRIBUTES; */
53 /* This is a simple list to keep track of the strings created
54 * by DdeCreateStringHandle. The list is used to free
55 * the strings whenever DdeUninitialize is called.
56 * This mechanism is not complete and does not handle multiple instances.
57 * Most of the DDE API use a DWORD parameter indicating which instance
58 * of a given program is calling them. The API are supposed to
59 * associate the data to the instance that created it.
61 typedef struct tagHSZNode HSZNode;
68 /* Start off the list pointer with a NULL.
70 static HSZNode* pHSZNodes = NULL;
73 /******************************************************************************
74 * RemoveHSZNodes (INTERNAL)
76 * Remove a node from the list of HSZ nodes.
78 ******************************************************************************
82 * Vn Date Author Comment
84 * 1.0 Dec 1998 Corel/Macadamian Initial version
87 static void RemoveHSZNode( DWORD idInst, HSZ hsz )
89 HSZNode* pPrev = NULL;
90 HSZNode* pCurrent = NULL;
92 /* Set the current node at the start of the list.
95 /* While we have more nodes.
97 while( pCurrent != NULL )
99 /* If we found the node we were looking for.
101 if( pCurrent->hsz == hsz )
105 /* If the first node in the list is to to be removed.
106 * Set the global list pointer to the next node.
108 if( pCurrent == pHSZNodes )
110 pHSZNodes = pCurrent->next;
112 /* Just fix the pointers has to skip the current
113 * node so we can delete it.
117 pPrev->next = pCurrent->next;
119 /* Destroy this node.
124 /* Save the previous node pointer.
127 /* Move on to the next node.
129 pCurrent = pCurrent->next;
133 /******************************************************************************
134 * FreeAndRemoveHSZNodes (INTERNAL)
136 * Frees up all the strings still allocated in the list and
137 * remove all the nodes from the list of HSZ nodes.
139 ******************************************************************************
143 * Vn Date Author Comment
145 * 1.0 Dec 1998 Corel/Macadamian Initial version
148 static void FreeAndRemoveHSZNodes( DWORD idInst )
150 /* Free any strings created in this instance.
152 while( pHSZNodes != NULL )
154 DdeFreeStringHandle32( idInst, pHSZNodes->hsz );
158 /******************************************************************************
159 * InsertHSZNode (INTERNAL)
161 * Insert a node to the head of the list.
163 ******************************************************************************
167 * Vn Date Author Comment
169 * 1.0 Dec 1998 Corel/Macadamian Initial version
172 static void InsertHSZNode( DWORD idInst, HSZ hsz )
176 HSZNode* pNew = NULL;
177 /* Create a new node for this HSZ.
179 pNew = (HSZNode*) malloc( sizeof( HSZNode ) );
182 /* Set the handle value.
185 /* Attach the node to the head of the list.
187 pNew->next = pHSZNodes;
188 /* The new node is now at the head of the list
189 * so set the global list pointer to it.
196 /******************************************************************************
197 * Release_reserved_mutex
199 * generic routine to release a reserved mutex
202 ******************************************************************************
206 * Vn Date Author Comment
208 * 1.0 Jan 1999 Keith Matthews Initial version
211 DWORD Release_reserved_mutex (HANDLE32 mutex, LPTSTR mutex_name, BOOL32 release_handle_m, BOOL32 release_this_i )
214 if ( (err_no=GetLastError()) != 0 )
216 ERR(ddeml,"ReleaseMutex failed - %s mutex %li\n",mutex_name,err_no);
217 HeapFree(GetProcessHeap(), 0, this_instance);
218 if ( release_handle_m )
220 ReleaseMutex(handle_mutex);
222 return DMLERR_SYS_ERROR;
224 if ( release_this_i )
226 HeapFree(GetProcessHeap(), 0, this_instance);
228 return DMLERR_NO_ERROR;
231 /******************************************************************************
232 * IncrementInstanceId
234 * generic routine to increment the max instance Id and allocate a new application instance
236 ******************************************************************************
240 * Vn Date Author Comment
242 * 1.0 Jan 1999 Keith Matthews Initial version
245 DWORD IncrementInstanceId()
247 SECURITY_ATTRIBUTES s_attrib;
248 /* Need to set up Mutex in case it is not already present */
249 // increment handle count & get value
250 if ( !inst_count_mutex )
252 s_attrib.bInheritHandle = TRUE;
253 s_attrib.lpSecurityDescriptor = NULL;
254 s_attrib.nLength = sizeof(s_attrib);
255 inst_count_mutex = CreateMutex32W(&s_attrib,1,DDEInstanceAccess); // 1st time through
257 WaitForSingleObject(inst_count_mutex,1000); // subsequent calls
258 /* FIXME - needs refinement with popup for timeout, also is timeout interval OK */
260 if ( (err_no=GetLastError()) == ERROR_INVALID_HANDLE )
262 ERR(ddeml,"CreateMutex failed - inst_count %li\n",err_no);
263 err_no=Release_reserved_mutex (handle_mutex,"handle_mutex",0,1);
264 return DMLERR_SYS_ERROR;
266 DDE_Max_Assigned_Instance++;
267 this_instance->Instance_id = DDE_Max_Assigned_Instance;
268 if (Release_reserved_mutex(inst_count_mutex,"instance_count",1,0)) return DMLERR_SYS_ERROR;
269 return DMLERR_NO_ERROR;
272 /******************************************************************************
273 * DdeInitialize16 (DDEML.2)
275 UINT16 WINAPI DdeInitialize16( LPDWORD pidInst, PFNCALLBACK16 pfnCallback,
276 DWORD afCmd, DWORD ulRes)
278 return (UINT16)DdeInitialize32A(pidInst,(PFNCALLBACK32)pfnCallback,
283 /******************************************************************************
284 * DdeInitialize32A (USER32.106)
286 UINT32 WINAPI DdeInitialize32A( LPDWORD pidInst, PFNCALLBACK32 pfnCallback,
287 DWORD afCmd, DWORD ulRes )
289 return DdeInitialize32W(pidInst,pfnCallback,afCmd,ulRes);
293 /******************************************************************************
294 * DdeInitialize32W [USER32.107]
295 * Registers an application with the DDEML
298 * pidInst [I] Pointer to instance identifier
299 * pfnCallback [I] Pointer to callback function
300 * afCmd [I] Set of command and filter flags
304 * Success: DMLERR_NO_ERROR
305 * Failure: DMLERR_DLL_USAGE, DMLERR_INVALIDPARAMETER, DMLERR_SYS_ERROR
307 ******************************************************************************
311 * Vn Date Author Comment
313 * 1.0 Pre 1998 Alexandre/Len Initial Stub
314 * 1.1 Jan 1999 Keith Matthews Initial (near-)complete version
317 UINT32 WINAPI DdeInitialize32W( LPDWORD pidInst, PFNCALLBACK32 pfnCallback,
318 DWORD afCmd, DWORD ulRes )
320 DDE_HANDLE_ENTRY *reference_inst;
321 SECURITY_ATTRIBUTES s_attrib;
324 // probably not really capable of handling mutliple processes, but should handle
325 // multiple instances within one process
329 ERR(dde, "Reserved value not zero? What does this mean?\n");
330 FIXME(ddeml, "(%p,%p,0x%lx,%ld): stub\n",pidInst,pfnCallback,afCmd,ulRes);
331 /* trap this and no more until we know more */
332 return DMLERR_NO_ERROR;
336 /* can't set up the instance with nothing to act as a callback */
337 TRACE(ddeml,"No callback provided\n");
338 return DMLERR_INVALIDPARAMETER; /* might be DMLERR_DLL_USAGE */
341 /* grab enough heap for one control struct - not really necessary for re-initialise
342 but allows us to use same validation routines */
343 this_instance= (DDE_HANDLE_ENTRY*)HeapAlloc( SystemHeap, 0, sizeof(DDE_HANDLE_ENTRY) );
344 if ( this_instance == NULL )
346 // catastrophe !! warn user & abort
347 ERR (ddeml,"Instance create failed - out of memory\n");
348 return DMLERR_SYS_ERROR;
350 this_instance->Next_Entry = NULL;
351 this_instance->Monitor=(afCmd|APPCLASS_MONITOR);
353 // messy bit, spec implies that 'Client Only' can be set in 2 different ways, catch 1 here
355 this_instance->Client_only=afCmd&APPCMD_CLIENTONLY;
356 this_instance->Instance_id = pidInst; // May need to add calling proc Id
357 this_instance->CallBack=*pfnCallback;
358 this_instance->Txn_count=0;
359 this_instance->Unicode = TRUE;
360 this_instance->Win16 = FALSE;
361 this_instance->Monitor_flags = afCmd & MF_MASK;
363 // isolate CBF flags in one go, expect this will go the way of all attempts to be clever !!
365 this_instance->CBF_Flags=afCmd^((afCmd&MF_MASK)|((afCmd&APPCMD_MASK)|(afCmd&APPCLASS_MASK)));
367 if ( ! this_instance->Client_only )
370 // Check for other way of setting Client-only !!
372 this_instance->Client_only=(this_instance->CBF_Flags&CBF_FAIL_ALLSVRXACTIONS)
373 ==CBF_FAIL_ALLSVRXACTIONS;
376 TRACE(ddeml,"instance created - checking validity \n");
378 if( *pidInst == 0 ) {
379 /* Initialisation of new Instance Identifier */
380 TRACE(ddeml,"new instance, callback %p flags %lX\n",pfnCallback,afCmd);
381 /* Need to set up Mutex in case it is not already present */
382 s_att->bInheritHandle = TRUE;
383 s_att->lpSecurityDescriptor = NULL;
384 s_att->nLength = sizeof(s_att);
385 handle_mutex = CreateMutex32W(s_att,1,DDEHandleAccess);
386 if ( (err_no=GetLastError()) == ERROR_INVALID_HANDLE )
388 ERR(ddeml,"CreateMutex failed - handle list %li\n",err_no);
389 HeapFree(GetProcessHeap(), 0, this_instance);
390 return DMLERR_SYS_ERROR;
392 TRACE(ddeml,"Handle Mutex created/reserved\n");
393 if (DDE_Handle_Table_Base == NULL )
395 /* can't be another instance in this case, assign to the base pointer */
396 DDE_Handle_Table_Base= this_instance;
398 // since first must force filter of XTYP_CONNECT and XTYP_WILDCONNECT for
400 // ------------------------------- NOTE NOTE NOTE --------------------------
402 // the manual is not clear if this condition
403 // applies to the first call to DdeInitialize from an application, or the
404 // first call for a given callback !!!
407 this_instance->CBF_Flags=this_instance->CBF_Flags|APPCMD_FILTERINITS;
408 TRACE(ddeml,"First application instance detected OK\n");
409 // allocate new instance ID
410 if ((err_no = IncrementInstanceId()) ) return err_no;
412 /* really need to chain the new one in to the latest here, but after checking conditions
413 such as trying to start a conversation from an application trying to monitor */
414 reference_inst = DDE_Handle_Table_Base;
415 TRACE(ddeml,"Subsequent application instance - starting checks\n");
416 while ( reference_inst->Next_Entry != NULL )
419 // This set of tests will work if application uses same instance Id
420 // at application level once allocated - which is what manual implies
421 // should happen. If someone tries to be
422 // clever (lazy ?) it will fail to pick up that later calls are for
423 // the same application - should we trust them ?
425 if ( this_instance->Instance_id == reference_inst->Instance_id)
427 // Check 1 - must be same Client-only state
429 if ( this_instance->Client_only != reference_inst->Client_only)
431 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,1))
432 return DMLERR_SYS_ERROR;
433 return DMLERR_DLL_USAGE;
436 // Check 2 - cannot use 'Monitor' with any non-monitor modes
438 if ( this_instance->Monitor != reference_inst->Monitor)
440 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,1))
441 return DMLERR_SYS_ERROR;
442 return DMLERR_INVALIDPARAMETER;
445 // Check 3 - must supply different callback address
447 if ( this_instance->CallBack == reference_inst->CallBack)
449 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,1))
450 return DMLERR_SYS_ERROR;
451 return DMLERR_DLL_USAGE;
454 reference_inst = reference_inst->Next_Entry;
456 // All cleared, add to chain
458 TRACE(ddeml,"Application Instance checks finished\n");
459 if ((err_no = IncrementInstanceId())) return err_no;
460 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,0)) return DMLERR_SYS_ERROR;
461 reference_inst->Next_Entry = this_instance;
463 pidInst = (LPDWORD)this_instance->Instance_id;
464 TRACE(ddeml,"New application instance processing finished OK\n");
466 /* Reinitialisation situation --- FIX */
467 TRACE(ddeml,"reinitialisation of (%p,%p,0x%lx,%ld): stub\n",pidInst,pfnCallback,afCmd,ulRes);
468 WaitForSingleObject(handle_mutex,1000);
469 if ( (err_no=GetLastError()) != 0 )
472 /* FIXME - needs refinement with popup for timeout, also is timeout interval OK */
474 ERR(ddeml,"WaitForSingleObject failed - handle list %li\n",err_no);
475 HeapFree(GetProcessHeap(), 0, this_instance);
476 return DMLERR_SYS_ERROR;
478 if (DDE_Handle_Table_Base == NULL )
480 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,1)) return DMLERR_SYS_ERROR;
481 return DMLERR_DLL_USAGE;
483 HeapFree(GetProcessHeap(), 0, this_instance); // finished - release heap space used as work store
484 // can't reinitialise if we have initialised nothing !!
485 reference_inst = DDE_Handle_Table_Base;
486 /* must first check if we have been given a valid instance to re-initialise !! how do we do that ? */
487 while ( reference_inst->Next_Entry != NULL )
489 if ( pidInst == reference_inst->Instance_id && pfnCallback == reference_inst->CallBack )
491 // Check 1 - cannot change client-only mode if set via APPCMD_CLIENTONLY
493 if ( reference_inst->Client_only )
495 if ((reference_inst->CBF_Flags & CBF_FAIL_ALLSVRXACTIONS) != CBF_FAIL_ALLSVRXACTIONS)
497 // i.e. Was set to Client-only and through APPCMD_CLIENTONLY
499 if ( ! ( afCmd & APPCMD_CLIENTONLY))
501 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,1))
502 return DMLERR_SYS_ERROR;
503 return DMLERR_DLL_USAGE;
507 // Check 2 - cannot change monitor modes
509 if ( this_instance->Monitor != reference_inst->Monitor)
511 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,1))
512 return DMLERR_SYS_ERROR;
513 return DMLERR_DLL_USAGE;
516 // Check 3 - trying to set Client-only via APPCMD when not set so previously
518 if (( afCmd&APPCMD_CLIENTONLY) && ! reference_inst->Client_only )
520 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,1))
521 return DMLERR_SYS_ERROR;
522 return DMLERR_DLL_USAGE;
526 // All checked - change relevant flags
528 reference_inst->CBF_Flags = this_instance->CBF_Flags;
529 reference_inst->Client_only = this_instance->Client_only;
530 reference_inst->Monitor_flags = this_instance->Monitor_flags;
531 if ( Release_reserved_mutex(handle_mutex,"handle_mutex",0,1))
532 return DMLERR_SYS_ERROR;
535 return DMLERR_NO_ERROR;
539 /*****************************************************************
540 * DdeUninitialize16 (DDEML.3)
542 BOOL16 WINAPI DdeUninitialize16( DWORD idInst )
544 return (BOOL16)DdeUninitialize32( idInst );
548 /*****************************************************************
549 * DdeUninitialize32 [USER32.119] Frees DDEML resources
552 * idInst [I] Instance identifier
558 BOOL32 WINAPI DdeUninitialize32( DWORD idInst )
561 FIXME(ddeml, "(%ld): stub\n", idInst);
563 /* Free the nodes that were not freed by this instance
564 * and remove the nodes from the list of HSZ nodes.
566 FreeAndRemoveHSZNodes( idInst );
572 /*****************************************************************
573 * DdeConnectList16 [DDEML.4]
575 HCONVLIST WINAPI DdeConnectList16( DWORD idInst, HSZ hszService, HSZ hszTopic,
576 HCONVLIST hConvList, LPCONVCONTEXT16 pCC )
578 return DdeConnectList32(idInst, hszService, hszTopic, hConvList,
579 (LPCONVCONTEXT32)pCC);
583 /******************************************************************************
584 * DdeConnectList32 [USER32.93] Establishes conversation with DDE servers
587 * idInst [I] Instance identifier
588 * hszService [I] Handle to service name string
589 * hszTopic [I] Handle to topic name string
590 * hConvList [I] Handle to conversation list
591 * pCC [I] Pointer to structure with context data
594 * Success: Handle to new conversation list
597 HCONVLIST WINAPI DdeConnectList32( DWORD idInst, HSZ hszService, HSZ hszTopic,
598 HCONVLIST hConvList, LPCONVCONTEXT32 pCC )
600 FIXME(ddeml, "(%ld,%ld,%ld,%ld,%p): stub\n", idInst, hszService, hszTopic,
606 /*****************************************************************
607 * DdeQueryNextServer16 [DDEML.5]
609 HCONV WINAPI DdeQueryNextServer16( HCONVLIST hConvList, HCONV hConvPrev )
611 return DdeQueryNextServer32(hConvList, hConvPrev);
615 /*****************************************************************
616 * DdeQueryNextServer32 [USER32.112]
618 HCONV WINAPI DdeQueryNextServer32( HCONVLIST hConvList, HCONV hConvPrev )
620 FIXME(ddeml, "(%ld,%ld): stub\n",hConvList,hConvPrev);
624 /*****************************************************************
625 * DdeQueryString32A [USER32.113]
627 DWORD WINAPI DdeQueryString32A(DWORD idInst, HSZ hsz, LPSTR psz, DWORD cchMax, INT32 iCodePage)
630 CHAR pString[MAX_BUFFER_LEN];
633 "(%ld, 0x%lx, %p, %ld, %d): stub\n",
640 if( iCodePage == CP_WINANSI )
642 /* If psz is null, we have to return only the length
648 cchMax = MAX_BUFFER_LEN;
651 ret = GlobalGetAtomName32A( hsz, (LPSTR)psz, cchMax );
657 /*****************************************************************
658 * DdeQueryString32W [USER32.114]
660 DWORD WINAPI DdeQueryString32W(DWORD idInst, HSZ hsz, LPWSTR psz, DWORD cchMax, INT32 iCodePage)
663 WCHAR pString[MAX_BUFFER_LEN];
667 "(%ld, 0x%lx, %p, %ld, %d): stub\n",
674 if( iCodePage == CP_WINUNICODE )
676 /* If psz is null, we have to return only the length
682 cchMax = MAX_BUFFER_LEN;
683 /* Note: According to documentation if the psz parameter
684 * was NULL this API must return the length of the string in bytes.
686 factor = (int) sizeof(WCHAR)/sizeof(BYTE);
688 ret = GlobalGetAtomName32W( hsz, (LPWSTR)psz, cchMax ) * factor;
694 /*****************************************************************
695 * DdeDisconnectList (DDEML.6)
697 BOOL16 WINAPI DdeDisconnectList16( HCONVLIST hConvList )
699 return (BOOL16)DdeDisconnectList32(hConvList);
703 /******************************************************************************
704 * DdeDisconnectList32 [USER32.98] Destroys list and terminates conversations
710 BOOL32 WINAPI DdeDisconnectList32(
711 HCONVLIST hConvList) /* [in] Handle to conversation list */
713 FIXME(ddeml, "(%ld): stub\n", hConvList);
718 /*****************************************************************
719 * DdeConnect16 (DDEML.7)
721 HCONV WINAPI DdeConnect16( DWORD idInst, HSZ hszService, HSZ hszTopic,
722 LPCONVCONTEXT16 pCC )
724 FIXME( ddeml, "empty stub\n" );
729 /*****************************************************************
730 * DdeConnect32 (USER32.92)
732 HCONV WINAPI DdeConnect32( DWORD idInst, HSZ hszService, HSZ hszTopic,
733 LPCONVCONTEXT32 pCC )
735 FIXME(ddeml, "(0x%lx,%ld,%ld,%p): stub\n",idInst,hszService,hszTopic,
741 /*****************************************************************
742 * DdeDisconnect16 (DDEML.8)
744 BOOL16 WINAPI DdeDisconnect16( HCONV hConv )
746 return (BOOL16)DdeDisconnect32( hConv );
749 /*****************************************************************
750 * DdeSetUserHandle (DDEML.10)
752 BOOL16 WINAPI DdeSetUserHandle( HCONV hConv, DWORD id, DWORD hUser )
754 FIXME( ddeml, "(%ld,%ld,%ld): stub\n",hConv,id, hUser );
758 /*****************************************************************
759 * DdeCreateDataHandle16 (DDEML.14)
761 HDDEDATA WINAPI DdeCreateDataHandle16( DWORD idInst, LPBYTE pSrc, DWORD cb,
762 DWORD cbOff, HSZ hszItem, UINT16 wFmt,
765 return DdeCreateDataHandle32(idInst,
774 /*****************************************************************
775 * DdeCreateDataHandle32 (USER32.94)
777 HDDEDATA WINAPI DdeCreateDataHandle32( DWORD idInst, LPBYTE pSrc, DWORD cb,
778 DWORD cbOff, HSZ hszItem, UINT32 wFmt,
782 "(%ld,%p,%ld,%ld,0x%lx,%d,%d): stub\n",
794 /*****************************************************************
795 * DdeDisconnect32 (USER32.97)
797 BOOL32 WINAPI DdeDisconnect32( HCONV hConv )
799 FIXME( ddeml, "empty stub\n" );
804 /*****************************************************************
805 * DdeReconnect (DDEML.37) (USER32.115)
807 HCONV WINAPI DdeReconnect( HCONV hConv )
809 FIXME( ddeml, "empty stub\n" );
814 /*****************************************************************
815 * DdeCreateStringHandle16 (DDEML.21)
817 HSZ WINAPI DdeCreateStringHandle16( DWORD idInst, LPCSTR str, INT16 codepage )
819 return DdeCreateStringHandle32A( idInst, str, codepage );
823 /*****************************************************************
824 * DdeCreateStringHandle32A [USER32.95]
827 * Success: String handle
830 HSZ WINAPI DdeCreateStringHandle32A( DWORD idInst, LPCSTR psz, INT32 codepage )
833 TRACE(ddeml, "(%ld,%s,%d): stub\n",idInst,debugstr_a(psz),codepage);
835 if (codepage==CP_WINANSI)
837 hsz = GlobalAddAtom32A (psz);
838 /* Save the handle so we know to clean it when
839 * uninitialize is called.
841 InsertHSZNode( idInst, hsz );
848 /******************************************************************************
849 * DdeCreateStringHandle32W [USER32.96] Creates handle to identify string
852 * Success: String handle
855 HSZ WINAPI DdeCreateStringHandle32W(
856 DWORD idInst, /* [in] Instance identifier */
857 LPCWSTR psz, /* [in] Pointer to string */
858 INT32 codepage) /* [in] Code page identifier */
862 FIXME(ddeml, "(%ld,%s,%d): stub\n",idInst,debugstr_w(psz),codepage);
864 if (codepage==CP_WINUNICODE)
866 hsz = GlobalAddAtom32W (psz);
867 /* Save the handle so we know to clean it when
868 * uninitialize is called.
870 InsertHSZNode( idInst, hsz );
877 /*****************************************************************
878 * DdeFreeStringHandle16 (DDEML.22)
880 BOOL16 WINAPI DdeFreeStringHandle16( DWORD idInst, HSZ hsz )
882 return (BOOL32)DdeFreeStringHandle32( idInst, hsz );
886 /*****************************************************************
887 * DdeFreeStringHandle32 (USER32.101)
888 * RETURNS: success: nonzero
891 BOOL32 WINAPI DdeFreeStringHandle32( DWORD idInst, HSZ hsz )
893 TRACE( ddeml, "(%ld,%ld): stub\n",idInst, hsz );
894 /* Remove the node associated with this HSZ.
896 RemoveHSZNode( idInst, hsz );
897 /* Free the string associated with this HSZ.
899 return GlobalDeleteAtom (hsz) ? 0 : hsz;
903 /*****************************************************************
904 * DdeFreeDataHandle16 (DDEML.19)
906 BOOL16 WINAPI DdeFreeDataHandle16( HDDEDATA hData )
908 return (BOOL32)DdeFreeDataHandle32( hData );
912 /*****************************************************************
913 * DdeFreeDataHandle32 (USER32.100)
915 BOOL32 WINAPI DdeFreeDataHandle32( HDDEDATA hData )
917 FIXME( ddeml, "empty stub\n" );
924 /*****************************************************************
925 * DdeKeepStringHandle16 (DDEML.24)
927 BOOL16 WINAPI DdeKeepStringHandle16( DWORD idInst, HSZ hsz )
929 return (BOOL32)DdeKeepStringHandle32( idInst, hsz );
933 /*****************************************************************
934 * DdeKeepStringHandle32 (USER32.108)
936 BOOL32 WINAPI DdeKeepStringHandle32( DWORD idInst, HSZ hsz )
938 FIXME( ddeml, "empty stub\n" );
943 /*****************************************************************
944 * DdeClientTransaction16 (DDEML.11)
946 HDDEDATA WINAPI DdeClientTransaction16( LPVOID pData, DWORD cbData,
947 HCONV hConv, HSZ hszItem, UINT16 wFmt,
948 UINT16 wType, DWORD dwTimeout,
951 return DdeClientTransaction32( (LPBYTE)pData, cbData, hConv, hszItem,
952 wFmt, wType, dwTimeout, pdwResult );
956 /*****************************************************************
957 * DdeClientTransaction32 (USER32.90)
959 HDDEDATA WINAPI DdeClientTransaction32( LPBYTE pData, DWORD cbData,
960 HCONV hConv, HSZ hszItem, UINT32 wFmt,
961 UINT32 wType, DWORD dwTimeout,
964 FIXME( ddeml, "empty stub\n" );
968 /*****************************************************************
969 * DdeAbandonTransaction (DDEML.12)
971 BOOL16 WINAPI DdeAbandonTransaction( DWORD idInst, HCONV hConv,
972 DWORD idTransaction )
974 FIXME( ddeml, "empty stub\n" );
979 /*****************************************************************
980 * DdePostAdvise16 [DDEML.13]
982 BOOL16 WINAPI DdePostAdvise16( DWORD idInst, HSZ hszTopic, HSZ hszItem )
984 return (BOOL16)DdePostAdvise32(idInst, hszTopic, hszItem);
988 /******************************************************************************
989 * DdePostAdvise32 [USER32.110] Send transaction to DDE callback function.
995 BOOL32 WINAPI DdePostAdvise32(
996 DWORD idInst, /* [in] Instance identifier */
997 HSZ hszTopic, /* [in] Handle to topic name string */
998 HSZ hszItem) /* [in] Handle to item name string */
1000 FIXME(ddeml, "(%ld,%ld,%ld): stub\n",idInst,hszTopic,hszItem);
1005 /*****************************************************************
1006 * DdeAddData (DDEML.15)
1008 HDDEDATA WINAPI DdeAddData( HDDEDATA hData, LPBYTE pSrc, DWORD cb,
1011 FIXME( ddeml, "empty stub\n" );
1016 /******************************************************************************
1017 * DdeGetData32 [USER32.102] Copies data from DDE object ot local buffer
1020 * Size of memory object associated with handle
1022 DWORD WINAPI DdeGetData32(
1023 HDDEDATA hData, /* [in] Handle to DDE object */
1024 LPBYTE pDst, /* [in] Pointer to destination buffer */
1025 DWORD cbMax, /* [in] Amount of data to copy */
1026 DWORD cbOff) /* [in] Offset to beginning of data */
1028 FIXME(ddeml, "(%ld,%p,%ld,%ld): stub\n",hData,pDst,cbMax,cbOff);
1033 /*****************************************************************
1034 * DdeGetData16 [DDEML.16]
1036 DWORD WINAPI DdeGetData16(
1042 return DdeGetData32(hData, pDst, cbMax, cbOff);
1046 /*****************************************************************
1047 * DdeAccessData16 (DDEML.17)
1049 LPBYTE WINAPI DdeAccessData16( HDDEDATA hData, LPDWORD pcbDataSize )
1051 return DdeAccessData32(hData, pcbDataSize);
1054 /*****************************************************************
1055 * DdeAccessData32 (USER32.88)
1057 LPBYTE WINAPI DdeAccessData32( HDDEDATA hData, LPDWORD pcbDataSize )
1059 FIXME( ddeml, "(%ld,%p): stub\n", hData, pcbDataSize);
1063 /*****************************************************************
1064 * DdeUnaccessData16 (DDEML.18)
1066 BOOL16 WINAPI DdeUnaccessData16( HDDEDATA hData )
1068 return DdeUnaccessData32(hData);
1071 /*****************************************************************
1072 * DdeUnaccessData32 (USER32.118)
1074 BOOL32 WINAPI DdeUnaccessData32( HDDEDATA hData )
1076 FIXME( ddeml, "(0x%lx): stub\n", hData);
1081 /*****************************************************************
1082 * DdeEnableCallback16 (DDEML.26)
1084 BOOL16 WINAPI DdeEnableCallback16( DWORD idInst, HCONV hConv, UINT16 wCmd )
1086 return DdeEnableCallback32(idInst, hConv, wCmd);
1089 /*****************************************************************
1090 * DdeEnableCallback32 (USER32.99)
1092 BOOL32 WINAPI DdeEnableCallback32( DWORD idInst, HCONV hConv, UINT32 wCmd )
1094 FIXME( ddeml, "(%ld, 0x%lx, %d) stub\n", idInst, hConv, wCmd);
1099 /*****************************************************************
1100 * DdeNameService16 (DDEML.27)
1102 HDDEDATA WINAPI DdeNameService16( DWORD idInst, HSZ hsz1, HSZ hsz2,
1105 return DdeNameService32( idInst, hsz1, hsz2, afCmd );
1109 /******************************************************************************
1110 * DdeNameService32 [USER32.109] {Un}registers service name of DDE server
1113 * idInst [I] Instance identifier
1114 * hsz1 [I] Handle to service name string
1116 * afCmd [I] Service name flags
1122 HDDEDATA WINAPI DdeNameService32( DWORD idInst, HSZ hsz1, HSZ hsz2,
1125 FIXME(ddeml, "(%ld,%ld,%ld,%d): stub\n",idInst,hsz1,hsz2,afCmd);
1130 /*****************************************************************
1131 * DdeGetLastError16 (DDEML.20)
1133 UINT16 WINAPI DdeGetLastError16( DWORD idInst )
1135 return (UINT16)DdeGetLastError32( idInst );
1139 /******************************************************************************
1140 * DdeGetLastError32 [USER32.103] Gets most recent error code
1143 * idInst [I] Instance identifier
1148 UINT32 WINAPI DdeGetLastError32( DWORD idInst )
1150 FIXME(ddeml, "(%ld): stub\n",idInst);
1155 /*****************************************************************
1156 * DdeCmpStringHandles16 (DDEML.36)
1158 int WINAPI DdeCmpStringHandles16( HSZ hsz1, HSZ hsz2 )
1160 return DdeCmpStringHandles32(hsz1, hsz2);
1163 /*****************************************************************
1164 * DdeCmpStringHandles32 (USER32.91)
1166 * Compares the value of two string handles. This comparison is
1167 * not case sensitive.
1170 * -1 The value of hsz1 is zero or less than hsz2
1171 * 0 The values of hsz 1 and 2 are the same or both zero.
1172 * 1 The value of hsz2 is zero of less than hsz1
1174 int WINAPI DdeCmpStringHandles32( HSZ hsz1, HSZ hsz2 )
1176 CHAR psz1[MAX_BUFFER_LEN];
1177 CHAR psz2[MAX_BUFFER_LEN];
1181 TRACE( ddeml, "handle 1, handle 2\n" );
1183 ret1 = GlobalGetAtomName32A( hsz1, psz1, MAX_BUFFER_LEN );
1184 ret2 = GlobalGetAtomName32A( hsz2, psz2, MAX_BUFFER_LEN );
1185 /* Make sure we found both strings.
1187 if( ret1 == 0 && ret2 == 0 )
1189 /* If both are not found, return both "zero strings".
1193 else if( ret1 == 0 )
1195 /* If hsz1 is a not found, return hsz1 is "zero string".
1199 else if( ret2 == 0 )
1201 /* If hsz2 is a not found, return hsz2 is "zero string".
1207 /* Compare the two strings we got ( case insensitive ).
1209 ret = strcasecmp( psz1, psz2 );
1210 /* Since strcmp returns any number smaller than
1211 * 0 when the first string is found to be less than
1212 * the second one we must make sure we are returning
1213 * the proper values.
1228 /*****************************************************************
1229 * PackDDElParam (USER32.414)
1235 UINT32 WINAPI PackDDElParam(UINT32 msg, UINT32 uiLo, UINT32 uiHi)
1237 FIXME(ddeml, "stub.\n");
1242 /*****************************************************************
1243 * UnpackDDElParam (USER32.562)
1249 UINT32 WINAPI UnpackDDElParam(UINT32 msg, UINT32 lParam,
1250 UINT32 *uiLo, UINT32 *uiHi)
1252 FIXME(ddeml, "stub.\n");
1257 /*****************************************************************
1258 * FreeDDElParam (USER32.204)
1264 UINT32 WINAPI FreeDDElParam(UINT32 msg, UINT32 lParam)
1266 FIXME(ddeml, "stub.\n");
1270 /*****************************************************************
1271 * ReuseDDElParam (USER32.446)
1274 UINT32 WINAPI ReuseDDElParam(UINT32 lParam, UINT32 msgIn, UINT32 msgOut,
1275 UINT32 uiLi, UINT32 uiHi)
1277 FIXME(ddeml, "stub.\n");