|
|
/****************************************************************************/ /* */ /* PMDDE.C - */ /* */ /* Windows Program Starter DDE Routines */ /* */ /****************************************************************************/ #include "progman.h"
#include "dde.h"
#include "uniconv.h"
#define PMPrint(s) KdPrint(("PROGMAN: ")); \
KdPrint(s); \ KdPrint(("\n"));
//
// Define this if you want to know everything about Progman DDE
//
//#define VERBOSE_PROGMANDDE
#ifdef VERBOSE_PROGMANDDE
#define VerbosePrint(s) PMPrint(s)
#else
#define VerbosePrint(s)
#endif
/* DDE window classes */ TCHAR szProgmanDDE[] = TEXT("ProgmanDDE"); TCHAR szAppIconDDE[] = TEXT("AppIconDDE"); TCHAR szAppDescDDE[] = TEXT("AppDescDDE"); TCHAR szAppWDirDDE[] = TEXT("AppWDirDDE"); //
// For compatibility reasons, allow the old WIn3.1 Shell - AppProperties
// DDE connection.
//
TCHAR szAppProperties[] = TEXT("AppProperties");
BOOL bProgmanDDE = TRUE; BOOL bAppIconDDE = TRUE; BOOL bAppDescDDE = TRUE; BOOL bAppWDirDDE = TRUE;
/* application names*/ TCHAR szShell[] = TEXT("Shell");
/* topics*/ TCHAR szAppIcon[] = TEXT("AppIcon"); TCHAR szAppDesc[] = TEXT("AppDescription"); TCHAR szAppWDir[] = TEXT("AppWorkingDir"); TCHAR szSystem[] = TEXT("System");
/* items*/ TCHAR szGroupList[] = TEXT("Groups");
#define DDE_PROGMAN 0
#define APP_ICON 1
#define APP_DESC 2
#define APP_WDIR 3
#define WCHAR_QUOTE L'"'
BOOL fForcePoint = FALSE; /* used for replacement*/ POINT ptForce;
typedef struct _datadde { unsigned short unused:12, fResponse:1, fRelease:1, reserved:1, fAckReq:1; WORD cfFormat; } DATADDE;
typedef struct _newicondata { DATADDE dd; DWORD dwResSize; DWORD dwVer; BYTE iResource; } NEWICONDATA;
int NEAR PASCAL myatoi(LPTSTR lp); LPTSTR NEAR PASCAL SkipWhite(LPTSTR lpsz); LPTSTR APIENTRY GetOneParameter(LPTSTR lpCmd, WPARAM *lpW, BOOL bSaveQuotes); LPTSTR NEAR PASCAL GetCommandName(LPTSTR lpCmd, LPTSTR lpFormat, WPARAM *lpW); HANDLE NEAR PASCAL GetDDECommands(LPTSTR lpCmd, LPTSTR lpFormat);
typedef struct _ddeconversation { HWND hwndClient; HWND hwndServer; DWORD dwType; struct _ddeconversation *Next; } DDECONVERSATION, *PDDECONVERSATION;
PDDECONVERSATION pDdeConversation = NULL; /*--------------------------------------------------------------------------*/ /* */ /* InitDDEConverstionStruct() - */ /* */ /*--------------------------------------------------------------------------*/
VOID InitDdeConversationStruct() { pDdeConversation = (PDDECONVERSATION)LocalAlloc(LPTR, sizeof(DDECONVERSATION)); pDdeConversation->Next = NULL; }
/*--------------------------------------------------------------------------*/ /* */ /* AddDdeConverstion() - */ /* */ /*--------------------------------------------------------------------------*/
VOID AddDdeConversation(HWND hwndServer, HWND hwndClient, DWORD dwType) { PDDECONVERSATION pT = NULL;
if (!pDdeConversation) { return; } if (pT = (PDDECONVERSATION)LocalAlloc(LPTR, sizeof(DDECONVERSATION))) { pT->hwndServer = hwndServer; pT->hwndClient = hwndClient; pT->dwType = dwType; pT->Next = pDdeConversation->Next; pDdeConversation->Next = pT; } }
/*--------------------------------------------------------------------------*/ /* */ /* RemoveDdeConverstion() - */ /* */ /*--------------------------------------------------------------------------*/
VOID RemoveDdeConversation(HWND hwndServer, HWND hwndClient, DWORD dwType) { PDDECONVERSATION pT; PDDECONVERSATION pFree;
if (!pDdeConversation) { return; } for (pT = pDdeConversation; pT->Next; pT = pT->Next) { if ((pT->Next->hwndClient == hwndClient) && (pT->Next->hwndServer == hwndServer) && (pT->Next->dwType == dwType)) { pFree = pT->Next; pT->Next = pT->Next->Next; LocalFree(pFree); return; } } }
/*--------------------------------------------------------------------------*/ /* */ /* IsDDEConverstion() - */ /* */ /*--------------------------------------------------------------------------*/
BOOL IsDdeConversation(HWND hwndServer, HWND hwndClient, DWORD dwType) { PDDECONVERSATION pT;
if (!pDdeConversation) { return(FALSE); } for (pT = pDdeConversation; pT->Next; pT = pT->Next) { if ((pT->Next->hwndClient == hwndClient) && (pT->Next->hwndServer == hwndServer) && (pT->Next->dwType == dwType)) { return(TRUE); } } return(FALSE); }
/*--------------------------------------------------------------------------*/ /* */ /* DDEFail() - */ /* */ /*--------------------------------------------------------------------------*/
VOID APIENTRY DDEFail(HWND hWnd, HWND hwndTo, ATOM aItem) { MPostWM_DDE_ACK(hwndTo, hWnd, ACK_NEG, aItem); }
/*--------------------------------------------------------------------------*/ /* */ /* SkipWhite() - */ /* */ /* Returns a pointer to the first non-whitespace character in a string. */ /* */ /*--------------------------------------------------------------------------*/
LPTSTR APIENTRY SkipWhite(LPTSTR lpsz) { /* prevent sign extension */ while (*lpsz && (TUCHAR)*lpsz <= (TUCHAR)TEXT(' ')) lpsz++;
return(lpsz); }
/*--------------------------------------------------------------------------*/ /* */ /* GetCommandName() - */ /* */ /* Extracts an alphabetic string and looks it up in a list of possible
/* commands, returning a pointer to the character after the command and
/* sticking the command index somewhere.
/*
/* lpFormat string syntax:
/* cmd\0cmd\0...\0\0
/*
/*--------------------------------------------------------------------------*/
LPTSTR APIENTRY GetCommandName(LPTSTR lpCmd, LPTSTR lpFormat, WPARAM *lpW) { register TCHAR chT; register WORD iCmd = 0; LPTSTR lpT;
/* Eat any white space. */ lpT = lpCmd = SkipWhite(lpCmd);
/* Find the end of the token. */ while (IsCharAlpha(*lpCmd)) lpCmd++;
/* Temporarily NULL terminate it. */ chT = *lpCmd; *lpCmd = TEXT('\0');
/* Look up the token in a list of commands. */ *lpW = (DWORD_PTR)0xFFFF; while (*lpFormat) { if (!lstrcmpi(lpFormat, lpT)) { *lpW = iCmd; break; } iCmd++; while (*lpFormat++) ; }
*lpCmd = chT;
return(lpCmd); }
/*--------------------------------------------------------------------------*/ /* */ /* ValidateFileName() - */ /* */ /* Checks if the given filename really exists. The filename passed */ /* in will have quotes around it, so this routine removes the quotes */ /* first. Returns TRUE if it is a valid file. */ /* */ /*--------------------------------------------------------------------------*/ BOOL APIENTRY ValidateFileName (LPTSTR lpFileName) { TCHAR chT; WORD wLen; LPTSTR lpEnd; BOOL bResult = FALSE; HANDLE hFile; WIN32_FIND_DATA fd;
// Save the last character (better be a quote), and move
// the terminating NULL one character forward.
wLen = (WORD)lstrlen (lpFileName); lpEnd = lpFileName + wLen - 1; chT = *lpEnd;
// MarkTa fix for spaces at the end of a filename
// Remove the spaces by moving the quote forward.
while (*(lpEnd-1) == TEXT(' ')) lpEnd--;
*lpEnd = TEXT('\0');
// Test if this is a file.
hFile = FindFirstFile(lpFileName+1, &fd);
if (hFile != INVALID_HANDLE_VALUE) { FindClose (hFile); bResult = TRUE; }
// Put back the character we removed eariler, and NULL terminate
*lpEnd = chT; *(lpEnd+1) = TEXT('\0');
return (bResult); }
/*--------------------------------------------------------------------------*/ /* */ /* GetOneParameter() - */ /* */ /* Reads a parameter out of a string removing leading and trailing whitespace.
/* Terminated by , or ). ] [ and ( are not allowed. Exception: quoted
/* strings are treated as a whole parameter and may contain []() and ,.
/* Places the offset of the first character of the parameter into some place
/* and NULL terminates the parameter.
/*
/*--------------------------------------------------------------------------*/
LPTSTR APIENTRY GetOneParameter(LPTSTR lpCmd, WPARAM *lpW, BOOL bSaveQuotes) { LPTSTR lpT; LPTSTR lpTemp; TCHAR chT; WORD wLen; LPTSTR lpEnd;
switch (*lpCmd) { case TEXT(','): *lpW = (DWORD_PTR)lpCmd; *lpCmd++ = 0; /* comma: becomes a NULL string */ break;
case TEXT('"'): /* quoted string... trim off " */
VerbosePrint (("Quoted parameter before parsing: %S", lpCmd)); VerbosePrint (("bSaveQuotes = %d", bSaveQuotes));
if (bSaveQuotes) { // Set the beginning marker at the quote then increment.
*lpW = (DWORD_PTR)lpCmd; ++lpCmd; } else { // Increment first to skip the quote
++lpCmd; *lpW = (DWORD_PTR)lpCmd; }
while (*lpCmd && *lpCmd != TEXT('"')) lpCmd++; if (!*lpCmd) return(NULL);
lpTemp = lpCmd; // lpTemp should point at the quote
lpCmd++;
if (bSaveQuotes) { chT = *lpCmd; *lpCmd = TEXT('\0');
VerbosePrint (("Checking %S to confirm that it really is a file.", *lpW)); if (!ValidateFileName ((LPTSTR) *lpW)) { // file doesn't exist. Remove the quotes.
VerbosePrint (("No, this isn't a file. Removing the quotes.")); *lpW = *lpW + sizeof (TCHAR); lpTemp = (LPTSTR)(*lpW) + lstrlen((LPTSTR) (*lpW)) - 1; *lpTemp = TEXT('\0'); VerbosePrint (("New string after removing the quotes: %S", *lpW)); } else {
//
// The quoted filename is valid, so now we want to test if
// the quotes are really necessary. To do this, remove
// the quotes, and then call CheckEscapes to look for funny
// characters.
//
VerbosePrint (("Yes, %S is a file. Checking if we really need these quotes", *lpW)); SheRemoveQuotes ((LPTSTR) *lpW); CheckEscapes ((LPTSTR) *lpW, lstrlen ((LPTSTR) *lpW) + 2); VerbosePrint (("After checking quotes we have %S", *lpW)); }
*lpCmd = chT; } else *lpTemp = TEXT(' ');
while (*lpCmd && *lpCmd != TEXT(')') && *lpCmd != TEXT(',')) lpCmd++; if (!*lpCmd) return(NULL);
if (*lpCmd == TEXT(',')) { *lpCmd = TEXT('\0'); lpCmd++; } else *lpCmd = TEXT('\0');
// Remove the space at the end of the string if the parser
// added it.
wLen = (WORD)lstrlen ((LPTSTR)(*lpW)); lpEnd = (LPTSTR)(*lpW) + wLen - 1; if (*lpEnd == TEXT (' ')) *lpEnd = TEXT('\0');
VerbosePrint (("Quoted parameter after parsing: %S", *lpW)); break;
case TEXT(')'): return(lpCmd); /* we ought not to hit this */
case TEXT('('): case TEXT('['): case TEXT(']'): return(NULL); /* these are illegal */
default: lpT = lpCmd; *lpW = (DWORD_PTR)lpT;
while (*lpCmd && *lpCmd != TEXT(',') && *lpCmd != TEXT(')')) { /* Check for illegal characters. */ if (*lpCmd == TEXT(']') || *lpCmd == TEXT('[') || *lpCmd == TEXT('(') ) return(NULL);
/* Remove trailing whitespace */ /* prevent sign extension */ if ((TUCHAR)*lpCmd > (TUCHAR)TEXT(' ')) lpT = lpCmd; lpCmd = CharNext(lpCmd); }
/* Eat any trailing comma. */ if (*lpCmd == TEXT(',')) lpCmd++;
/* NULL terminator after last nonblank character -- may write over
* terminating ')' but the caller checks for that because this is * a hack. */ lpT = CharNext(lpT); *lpT = TEXT('\0');
break; }
/* Return next unused character. */ return(lpCmd); }
/*--------------------------------------------------------------------------*/ /* */ /* GetDDECommands() - */ /* */ /* Called with: far pointer to a string to parse and a far pointer to a
/* list of sz's containing the allowed function names.
/* The function returns a global handle to an array of words containing
/* one or more command definitions. A command definition consists of
/* a command index, a parameter count, and that number of offsets. Each
/* offset is an offset to a parameter in lpCmd which is now zero terminated.
/* The list of command is terminated with -1.
/* If there was a syntax error the return value is NULL.
/* Caller must free block.
/*
/*--------------------------------------------------------------------------*/
HANDLE NEAR PASCAL GetDDECommands(LPTSTR lpCmd, LPTSTR lpFormat) { register WORD cParm; WORD cCmd = 0; register HANDLE hDDECmds; DWORD_PTR * lpW = NULL; BOOL bAddItem = FALSE;
/* Will allow up to 128 words, 64 single command (less with parms). */ /*
* Now these are 32bit, since the offset is now replaced by the * full pointer which is 32 bit. * * (And if they are 64bit, they get even bigger.) */ hDDECmds = GlobalAlloc(GHND, 128 * sizeof(DWORD_PTR)); if (!hDDECmds) return(NULL);
/* Get pointer to array. */ lpW = (DWORD_PTR *)GlobalLock(hDDECmds); while (*lpCmd) { /* Skip leading whitespace. */ lpCmd = SkipWhite(lpCmd);
/* Are we at a NULL? */ if (!*lpCmd) { /* Did we find any commands yet? */ if (cCmd) goto GDEExit; else goto GDEErrExit; }
/* Each command should be inside square brackets. */ if (*lpCmd != TEXT('[')) goto GDEErrExit; lpCmd++;
/* Get the command name. */ lpCmd = GetCommandName(lpCmd, lpFormat, lpW); if (*lpW == (DWORD_PTR)0xFFFF) goto GDEErrExit;
if (*lpW == 1) bAddItem = TRUE;
lpW++;
/* Start with zero parms. */ cParm = 0; lpCmd = SkipWhite(lpCmd);
/* Check for opening '(' */ if (*lpCmd == TEXT('(')) { lpCmd++;
/* Skip white space and then find some parameters (may be none). */ lpCmd = SkipWhite(lpCmd);
while (*lpCmd != TEXT(')')) { if (!*lpCmd) goto GDEErrExit;
/* Get the parameter. */ if (bAddItem && (cParm == 0 || cParm == 2 || cParm == 6)) { // In this case, we are working with filenames of
// the command line, icon path, or default directory of
// the AddItem command.
// We don't want to strip the quotes if they exist.
if (!(lpCmd = GetOneParameter(lpCmd, lpW + (++cParm), TRUE))) goto GDEErrExit; } else { // This is for every other parameter. The quotes will be
// stripped.
if (!(lpCmd = GetOneParameter(lpCmd, lpW + (++cParm), FALSE))) goto GDEErrExit; }
/* HACK: Did GOP replace a ')' with a NULL? */ if (!*lpCmd) break;
/* Find the next one or ')' */ lpCmd = SkipWhite(lpCmd); }
lpCmd++;
/* Skip the terminating stuff. */ lpCmd = SkipWhite(lpCmd); }
/* Set the count of parameters and then skip the parameters. */ *lpW++ = cParm; lpW += cParm;
/* We found one more command. */ cCmd++;
/* Commands must be in square brackets. */ if (*lpCmd != TEXT(']')) goto GDEErrExit; lpCmd++; }
GDEExit: /* Terminate the command list with -1. */ *lpW = (DWORD_PTR)0xFFFF;
GlobalUnlock(hDDECmds); return(hDDECmds);
GDEErrExit: GlobalUnlock(hDDECmds); GlobalFree(hDDECmds); return(NULL); }
/*--------------------------------------------------------------------------*/ /* */ /* IsParameterANumber() - */ /* */ /*--------------------------------------------------------------------------*/
BOOL APIENTRY IsParameterANumber(LPTSTR lp) { while (*lp) { if (*lp < TEXT('0') || *lp > TEXT('9')) return(FALSE); lp++; } return(TRUE); }
/*--------------------------------------------------------------------------*/ /* */ /* myatoi() - */ /* */ /*--------------------------------------------------------------------------*/
int APIENTRY myatoi(LPTSTR lp) { register int i = 0;
while (*lp >= TEXT('0') && *lp <= TEXT('9')) { i *= 10; i += (int)(*lp-TEXT('0')); lp++; } return(i); }
/*--------------------------------------------------------------------------*/ /* */ /* ExecuteHandler() - */ /* */ /* Handles WM_DDE_EXECUTE messages... */ /* */ /* return 0 if it fails */ /* 1 if it succeeds */ /* 2 if it succeeds and the command was ExitProgman */ /* */ /*--------------------------------------------------------------------------*/
DWORD APIENTRY ExecuteHandler(HANDLE hString) { register HWND hwndT; LPTSTR lpT; LPTSTR lpString; register HANDLE hCmd; DWORD_PTR * lpwCmd; DWORD dwRet = 0; PGROUP pGroup; LPGROUPDEF lpgd; WCHAR lpFmtinit[] = TEXT("CreateGroup#AddItem#DeleteGroup#ExitProgman#ShowGroup#DeleteItem#ReplaceItem#Reload#ChangeINIFile#"); LPTSTR lpFmt ;
lpFmt = lpFmtinit; /* Lock the command string. */ lpString = (LPTSTR)GlobalLock(hString); if(!lpString) return(0);
VerbosePrint(("Execute Handler received: %S", lpString));
#ifdef DEBUG_PROGMAN_DDE
{ TCHAR szDebug[300];
wsprintf (szDebug, TEXT("%d PROGMAN: Execute Handler recived: %s\r\n"), GetTickCount(), lpString); OutputDebugString(szDebug); } #endif
bInDDE = TRUE;
/* Parse the commands. */
// the following line does not work on build 363! TEXT string is truncated
// after "CreateGroup".
//hCmd = GetDDECommands(lpString, (LPTSTR)TEXT("CreateGroup\0AddItem\0DeleteGroup\0ExitProgman\0ShowGroup\0DeleteItem\0ReplaceItem\0Reload\0ChangeINIFile\0"));
// substitute nulls for '#'
while (*lpFmt) { if (*lpFmt == TEXT('#')) *lpFmt = (TCHAR) 0; lpFmt++ ; } lpFmt = lpFmtinit; // reset the pointer back to the begining
hCmd = GetDDECommands(lpString, lpFmt) ; if (!hCmd) goto DEHErrExit1;
/* Lock the list of commands and parameter offsets. */ lpwCmd = (DWORD_PTR *)GlobalLock(hCmd);
/* Execute each command. */ while (*lpwCmd != (DWORD_PTR)0xFFFF) {
switch (*lpwCmd++) { case 0: { INT cParm; INT nCommonGrp = -1; LPTSTR lpCommonGrp = NULL; LPTSTR lpGroupName;
/* [ CreateGroup ( groupname [, groupfile] [, common_group_flag] ) ] */ /*
* The groups are now in the registry thus no more group files * and therefore this is now replaced by * [ CreateGroup ( groupname ) ] * The groupfile is specified is ignored. This will cause an error * for compatability reasons. */
/*
* A new optional parameter is added to specify whether to create * a Common group or a Personal group. * 1 for Common Group * 0 for Personal Group * Only users with administrative rights can create/delete Common * groups. The default if this parameter is not specified is: * Common group if user has admin rights * Personal group if not */
/* Make sure that we have 1, 2 or 3 parameters, ignore the 2nd one
* if it represents a groupfile name. */ cParm = (INT)*lpwCmd++; if ((cParm < 1) || (cParm > 3)) goto DEHErrExit;
/* Get a pointer to the group name. */ lpT = (LPTSTR) *lpwCmd++;
VerbosePrint (("CreateGroup received: %S", lpT));
if (cParm == 3) { // skip group file parameter
lpwCmd++; }
if (cParm > 1) { //
// Test if the 2nd parameter is a groupfile name or the
// common group flag
//
if (IsParameterANumber((LPTSTR)*lpwCmd)) {
// get the common group flag
if ((nCommonGrp = myatoi((LPTSTR) *lpwCmd++)) && !AccessToCommonGroups) goto DEHErrExit;
} else { lpwCmd++; } }
/* Search for the group... if it already exists, activate it. */ hwndT = GetWindow(hwndMDIClient, GW_CHILD); while (hwndT) { /* Skip icon titles. */ if (!GetWindow(hwndT, GW_OWNER)) {
/* Compare the group title with the request. */ pGroup = (PGROUP)GetWindowLongPtr(hwndT, GWLP_PGROUP); if (lpgd = (LPGROUPDEF)GlobalLock(pGroup->hGroup)) {
lpGroupName = (LPTSTR) PTR(lpgd, lpgd->pName); GlobalUnlock(pGroup->hGroup); if (!lstrcmpi(lpT, lpGroupName)) { BOOL bContinueSearch = TRUE;
//
// First case is the app didn't request
// a specific type of group.
//
if (nCommonGrp == -1) {
//
// If the user has access to
// common groups (thus also has
// access to personal groups), or
// the existing group is personal,
// then we are finished.
//
if (AccessToCommonGroups || !pGroup->fCommon) { bContinueSearch = FALSE; } }
//
// Second case the app requested
// a common group match.
//
else if (nCommonGrp == 1) {
//
// If user has access to the common groups
// and the group found is common, then we
// are finished.
//
if (AccessToCommonGroups && pGroup->fCommon) { bContinueSearch = FALSE; } }
//
// Third case is the app requested
// a personal group match.
//
else if (nCommonGrp == 0) {
//
// Check to see if the group is also
// personal.
//
if (!pGroup->fCommon) { bContinueSearch = FALSE; } }
if (bContinueSearch) { hwndT = GetWindow(hwndT, GW_HWNDNEXT); continue; } else {
VerbosePrint (("CreateGroup: Activing group")); BringWindowToTop(hwndT); break; } } } } hwndT = GetWindow(hwndT, GW_HWNDNEXT); }
/* If we didn't find it, add it. */ if (!hwndT) { TCHAR szTemp[MAXITEMPATHLEN+1]; // Group name.
//
// If the app does care what type of group to create,
// the default is to create a common group if the
// user has admin privilages. Otherwise they get a
// personal group.
//
if (nCommonGrp == -1) {
if (AccessToCommonGroups) { nCommonGrp = 1; } else { nCommonGrp = 0; } }
lstrcpy(szTemp, lpT); VerbosePrint (("CreateGroup: Creating new group")); CreateNewGroup(szTemp, (nCommonGrp == 1)); }
break; }
case 1: { INT cParm; WORD iIconIndex; POINT pt; LPPOINT lppt; DWORD dwFlags = CI_SET_DOS_FULLSCRN; BOOL fMinimize; WORD wHotKey; TCHAR szExpPath[MAXITEMPATHLEN+1]; TCHAR szExpDir[MAXITEMPATHLEN+1]; HICON hIcon; TCHAR szT[MAX_PATH]; WORD id;
/* [ AddItem (command,name,icopath,index,pointx,pointy,
defdir,hotkey,fminimize) ] */ //
// pActiveGroup is non NULL when the user
// has an item or group properties dialog up in
// progman i.e. the user is working in progman
// while some other app is doing DDE.
// We can't have both play on the same group at
// the same time.
// johannec 5-13-93 bug 9513
//
if (pCurrentGroup == pActiveGroup) { PMPrint (("AddItem: DDE converstation started with the group you have open! Exiting.")); goto DEHErrExit; }
/* There must be at least a command string. */ if ((cParm = (INT)*lpwCmd++) < 1) { PMPrint (("AddItem: No command string!")); goto DEHErrExit; }
/* Make sure we have a reasonable number of parameters. */ if (cParm == 5 || cParm > 10) { PMPrint (("AddItem: Not enough or too many parameters!")); goto DEHErrExit; }
/* If all else fails, there must be a command string! */ lpT = (LPTSTR) *lpwCmd++; if (!*lpT) { PMPrint (("AddItem: Null pointer for command string!")); goto DEHErrExit; }
VerbosePrint (("AddItem: szPathField = %S", lpT)); lstrcpy(szPathField, lpT); lstrcpy(szExpPath, szPathField); DoEnvironmentSubst(szExpPath, CharSizeOf(szExpPath));
VerbosePrint (("AddItem: Expanded path = %S", szExpPath));
StripArgs(szExpPath);
VerbosePrint (("AddItem: Path after StripArgs call = %S", szExpPath));
if (*szExpPath != WCHAR_QUOTE) CheckEscapes(szExpPath, CharSizeOf(szExpPath));
VerbosePrint (("AddItem: Path after CheckEscapes call = %S", szExpPath));
/* Look for the name field. */ szNameField[0] = TEXT('\0'); if (cParm > 1) { /* Get the next parameter. */ lpT = (LPTSTR)*lpwCmd++;
if (lstrlen (lpT) > MAXITEMNAMELEN) lpT[MAXITEMNAMELEN] = TEXT('\0');
lstrcpy(szNameField, lpT); }
/* If none given, generate one from the command. */ if (szNameField[0] == TEXT('\0')) { // NB Use the unexpanded path.
BuildDescription(szNameField, szPathField); }
VerbosePrint (("AddItem: Name field will be: %S", szNameField));
/* Look for the icon's path. */ szIconPath[0] = TEXT('\0'); if (cParm > 2) { lpT = (LPTSTR)*lpwCmd++; lstrcpy(szIconPath,lpT);
VerbosePrint(("AddItem: An icon path was given of: %S", szIconPath)); StripArgs(szIconPath); // I am removing this call to CheckEscapes because
// the filenames could now have quotes around them.
// This call will automaticly add another set of quotes
// thus causing the wrong icon to be displayed.
// ericflo 2/25/94
//CheckEscapes(szIconPath, CharSizeOf(szIconPath));
VerbosePrint (("AddItem: After stripping args the icon path = %S", szIconPath)); } else szIconPath[0] = TEXT('\0');
/* Get the icon index. */ if (cParm > 3) { lpT = (LPTSTR)*lpwCmd++; iIconIndex = (WORD)myatoi(lpT); } else iIconIndex = 0;
if (iIconIndex >= 666) { iIconIndex -= 666; } else { dwFlags |= CI_ACTIVATE; }
//
// If there is no icon path, check if we have an executable associated
// with the command path.
//
if (!*szIconPath) { FindExecutable(szExpPath, szExpDir, szT); if (!*szT) { dwFlags |= CI_NO_ASSOCIATION; } } else { //
// convert the icon index to the icon id which is what progman
// uses.
//
lstrcpy(szT, szIconPath); id = iIconIndex; hIcon = ExtractAssociatedIcon(hAppInstance, szT, &id); if (lstrcmpi(szT, szIconPath)) { id = iIconIndex; } }
VerbosePrint (("AddItem: Icon index = %d", id));
/* Get the point :) Note x cannot be specified alone. */ if (cParm > 4) { lpT = (LPTSTR)*lpwCmd++; if (*lpT) { pt.x = myatoi(lpT); } else { pt.x = -1; } lpT = (LPTSTR)*lpwCmd++; if (*lpT) { pt.y = myatoi(lpT); } else { pt.x = -1; } lppt = (LPPOINT)&pt; } else lppt = (LPPOINT)NULL;
if (fForcePoint) { lppt = &ptForce; fForcePoint = FALSE; }
/* look to see if there is a default directory
*/ if (cParm > 6) { lpT = (LPTSTR)*lpwCmd++; VerbosePrint (("AddItem: Given this default direcotry: %S", lpT)); lstrcpy(szDirField, lpT); lstrcpy(szExpDir, lpT); DoEnvironmentSubst(szExpDir, CharSizeOf(szExpDir)); StripArgs(szExpDir); VerbosePrint(("AddItem: After expanding and strip args, we have: %S", szExpDir)); } else { szDirField[0] = TEXT('\0'); }
// If the directory is null then use the path bit
// of the command line. (Unexpanded)
if (!*szDirField) { GetDirectoryFromPath(szPathField, szDirField); if (*szDirField) { CheckEscapes (szDirField, MAXITEMPATHLEN+1); } }
VerbosePrint (("AddItem: Default directory is: %S", szDirField));
/* hotkey
*/ if (cParm > 7) { lpT = (LPTSTR)*lpwCmd++; wHotKey = (WORD)myatoi(lpT); } else wHotKey = 0;
/* fminimize
*/ if (cParm > 8) { lpT = (LPTSTR)*lpwCmd++; fMinimize = myatoi(lpT); } else fMinimize = FALSE;
/* fseparateVDM
*/ if (cParm > 9) { lpT = (LPTSTR)*lpwCmd++; if (myatoi(lpT)) { dwFlags |= CI_SEPARATE_VDM; VerbosePrint (("AddItem: Separate VDM flag specified")); } }
VerbosePrint (("AddItem: Results passed to CreateNewItem are:")); VerbosePrint ((" Name Field = %S", szNameField)); VerbosePrint ((" Path Field = %S", szPathField)); VerbosePrint ((" Icon Path = %S", szIconPath)); VerbosePrint ((" Dir Field = %S", szDirField)); VerbosePrint ((" Hot Key = %d", wHotKey)); VerbosePrint ((" Minimize = %d", fMinimize)); VerbosePrint ((" id = %d", id)); VerbosePrint ((" Icon Index = %d", iIconIndex)); VerbosePrint ((" Flags = %lx", dwFlags));
/* Now add the new item!!! */ if (!CreateNewItem(pCurrentGroup->hwnd, szNameField, szPathField, szIconPath, szDirField, wHotKey, fMinimize, id, iIconIndex, NULL, lppt, dwFlags)) goto DEHErrExit;
// Update scrollbars.
if ((bAutoArrange) && (!bAutoArranging)) ArrangeItems(pCurrentGroup->hwnd); else if (!bAutoArranging) CalcGroupScrolls(pCurrentGroup->hwnd);
break; }
case 2: { int cParm; BOOL fCommonGrp = FALSE; BOOL fCommonDefaulted = FALSE; LPTSTR lpGroupName; HWND hwndPersGrp = NULL;
/* [ DeleteGroup (group_name [, common_group_flag] ) ] */
/*
* A new optional parameter is added to specify whether to delete * a Common group or a Personal group. * 1 for Common Group * 0 for Personal Group * Only users with administrative rights can create/delete Common * groups. The default if this parameter is not specified is: * Common group if user has admin rights * Personal group if not */
/* Make sure that we have 1 or 2 parameter. */ cParm = (int)*lpwCmd++;
if ((cParm < 1) || (cParm > 2)) goto DEHErrExit;
/* Get a pointer to the group name. */ lpT = (LPTSTR) *lpwCmd++;
if (cParm == 2) { //
// Get the common group flag. The User must have Write and
// Delete access to the common groups.
//
if ((fCommonGrp = myatoi((LPTSTR) *lpwCmd++)) && !AccessToCommonGroups) goto DEHErrExit; } else if (AccessToCommonGroups) { //
// The default for a user with Write access rights to the Common
// Groups is deleting a common group.
//
fCommonGrp = TRUE; fCommonDefaulted = TRUE; }
/* Search for the group... */ hwndT = GetWindow(hwndMDIClient, GW_CHILD); while (hwndT) { /* Skip icon titles. */ if (!GetWindow(hwndT, GW_OWNER)) {
/* Compare the group title with the request. */ pGroup = (PGROUP)GetWindowLongPtr(hwndT, GWLP_PGROUP); if (lpgd = (LPGROUPDEF)GlobalLock(pGroup->hGroup)) {
lpGroupName = (LPTSTR) PTR(lpgd, lpgd->pName); GlobalUnlock(pGroup->hGroup); if (!lstrcmpi(lpT, lpGroupName)) { if ((fCommonGrp && !pGroup->fCommon) || (!fCommonGrp && pGroup->fCommon) ) {
//
// If the app did not specify common nor personal
// group and we defaulted to common group (because
// the user is an admin), then don't ignore the
// personal group that was found. If no common group
// is found, we'll default to the personal group.
// 5-7-93 johannec bug ????
//
if (fCommonGrp && fCommonDefaulted) { hwndPersGrp = hwndT; }
hwndT = GetWindow(hwndT, GW_HWNDNEXT); continue; } //
// pActiveGroup is non NULL when the user
// has an item or group properties dialog up in
// progman i.e. the user is working in progman
// while some other app is doing DDE.
// We can't have both play on the same group at
// the same time.
// johannec 5-13-93 bug 9513
//
if (pGroup == pActiveGroup) { goto DEHErrExit; } DeleteGroup(hwndT); break; } } } hwndT = GetWindow(hwndT, GW_HWNDNEXT); }
/* If we didn't find it, report the error. */ if (!hwndT) { if (hwndPersGrp) { //
// If a personal group was found instead of the common group
// delete it.
//
pGroup = (PGROUP)GetWindowLongPtr(hwndPersGrp, GWLP_PGROUP);
//
// pActiveGroup is non NULL when the user
// has an item or group properties dialog up in
// progman i.e. the user is working in progman
// while some other app is doing DDE.
// We can't have both play on the same group at
// the same time.
// johannec 5-13-93 bug 9513
//
if (pGroup == pActiveGroup) { goto DEHErrExit; } DeleteGroup(hwndPersGrp);
} else { goto DEHErrExit; } } break; }
case 3: /* [ ExitProgman (bSaveGroups) ] */
if (bExitWindows) goto DEHErrExit;
/* Make sure that we have 1 parameter. */ if (*lpwCmd++ != 1) goto DEHErrExit;
/* Get a pointer to the parm. */ lpT = (LPTSTR) *lpwCmd++;
bSaveSettings = FALSE; if (*lpT == TEXT('1')) WriteINIFile();
//
// The 2 is a magic return value inside of the
// DDEMsgProc routine.
//
dwRet = 2; goto DEHErrExit; break;
case 4: { INT cParm; int iShowCmd; BOOL fCommonGrp = FALSE; BOOL fCommonDefaulted = FALSE; HWND hwndPersGrp = NULL; TCHAR szT[MAXKEYLEN + 1]; TCHAR szCommonGroupSuffix[MAXKEYLEN + 1]; WINDOWPLACEMENT wp;
/* [ ShowGroup (group_name, wShowParm [, fCommonGroup] ) ] */
/*
* A new optional parameter is added to specify whether to show * a Common group or a Personal group. * 1 for Common Group * 0 for Personal Group * Only users with administrative rights can create/delete Common * groups. The default if this parameter is not specified is: * Common group if user has admin rights * Personal group if not */
/* Make sure that we have 2 or 3 parameters. */ cParm = (INT)*lpwCmd++; if ((cParm < 2) || (cParm > 3)) goto DEHErrExit;
/* Get a pointer to the group name. */ lpT = (LPTSTR) *lpwCmd++;
VerbosePrint (("ShowGroup: Called with %S", lpT));
iShowCmd = myatoi((LPTSTR) *lpwCmd++);
if (cParm == 3) { //
// get the common group flag
//
fCommonGrp = myatoi((LPTSTR) *lpwCmd++); } else if (AccessToCommonGroups) { //
// The default for a user with administrative rights is Common
// Groups.
//
fCommonGrp = TRUE; fCommonDefaulted = TRUE; }
/* Search for the group... */ hwndT = GetWindow(hwndMDIClient, GW_CHILD); while (hwndT) { //
// Skip icon titles.
//
if (GetWindow(hwndT, GW_OWNER)) { hwndT = GetWindow(hwndT, GW_HWNDNEXT); continue; }
/* Compare the group title with the request. */ pGroup = (PGROUP)GetWindowLongPtr(hwndT, GWLP_PGROUP); if (lpgd = (LPGROUPDEF)GlobalLock(pGroup->hGroup)) {
lstrcpy(szT, (LPTSTR) PTR(lpgd, lpgd->pName)); GlobalUnlock(pGroup->hGroup); if (!lstrcmpi(lpT, szT)) {
if ((fCommonGrp && !pGroup->fCommon) || (!fCommonGrp && pGroup->fCommon) ) { //
// If the app did not specify common nor personal
// group and we defaulted to common group (because
// the user is an admin), then don't ignore the
// personal group that was found. If no common group
// is found, we'll default to the personal group.
// 5-7-93 johannec bug ????
//
if (fCommonGrp && fCommonDefaulted) { hwndPersGrp = hwndT; }
hwndT = GetWindow(hwndT, GW_HWNDNEXT); continue; } ShowWindow(hwndT, iShowCmd); //
// if the group is common and not being minimized
// then must add the common suffix to the group
// window title. If the group is being minimized
// then make sure the common suffix is not there.
//
if (fCommonGrp) { wp.length = sizeof(WINDOWPLACEMENT); GetWindowPlacement(hwndT, &wp); if (wp.showCmd != SW_SHOWMINIMIZED && wp.showCmd != SW_MINIMIZE && wp.showCmd != SW_SHOWMINNOACTIVE ) { LoadString(hAppInstance, IDS_COMMONGRPSUFFIX, szCommonGroupSuffix, CharSizeOf(szCommonGroupSuffix)); lstrcat(szT, szCommonGroupSuffix); } SetWindowText(hwndT, szT); } SendMessage(hwndT, WM_ACTIVATE, 1, 0); break; } } hwndT = GetWindow(hwndT, GW_HWNDNEXT); }
/* If we didn't find it, report the error. */ if (!hwndT) { if (hwndPersGrp) { //
// If a personal group was found instead of the common group
// show it.
//
ShowWindow(hwndPersGrp, iShowCmd); SendMessage(hwndPersGrp, WM_ACTIVATE, 1, 0); } else { goto DEHErrExit; } } break; } case 6:
/* [ ReplaceItem (item_name) ] */ fForcePoint = TRUE; ptForce.x = -1; // in case we don't really find the item
ptForce.y = -1;
/* fall thru */
case 5: { PITEM pItem; LPITEMDEF lpid;
/* [ DeleteItem (item_name) ] */
//
// pActiveGroup is non NULL when the user
// has an item or group properties dialog up in
// progman i.e. the user is working in progman
// while some other app is doing DDE.
// We can't have both play on the same group at
// the same time.
// johannec 5-13-93 bug 9513
//
if (pCurrentGroup == pActiveGroup) { goto DEHErrExit; }
/* exactly one parameter
*/ if (*lpwCmd++ != 1) goto DEHErrExit;
lpT = (LPTSTR) *lpwCmd++;
lpgd = LockGroup(pCurrentGroup->hwnd); if (!lpgd) goto DEHErrExit;
for (pItem = pCurrentGroup->pItems; pItem; pItem = pItem->pNext) { lpid = ITEM(lpgd,pItem->iItem); if (!lstrcmpi((LPTSTR) PTR(lpgd, lpid->pName),lpT)) { ptForce.x = pItem->rcIcon.left; ptForce.y = pItem->rcIcon.top; UnlockGroup(pCurrentGroup->hwnd); DeleteItem(pCurrentGroup,pItem); break; } } if (!pItem) { UnlockGroup(pCurrentGroup->hwnd); goto DEHErrExit; }
break; }
case 7: { int cParm; BOOL fAll; BOOL fCommonGrp = FALSE;
/* [ Reload [(groupname [, common_group_flag] )] ] */
/*
* A new optional parameter is added to specify whether to reload * a Common group or a Personal group. * 1 for Common Group * 0 for Personal Group * Only users with administrative rights can create/delete Common * groups. The default if this parameter is not specified is: * Common group if user has admin rights * Personal group if not */
cParm = (int)*lpwCmd++;
if (!cParm) fAll = TRUE; else if ((cParm == 1) || (cParm == 2)) fAll = FALSE; else goto DEHErrExit;
if (fAll) { HWND hwndT;
ShowWindow(hwndMDIClient, SW_HIDE); ValidateRect(hwndProgman,NULL);
/* unload all the groups!
*/ for (hwndT = GetWindow(hwndMDIClient, GW_CHILD); hwndT; hwndT = GetWindow(hwndMDIClient, GW_CHILD)) {
/* Skip icon titles. */ while (GetWindow(hwndT, GW_OWNER)) { hwndT = GetWindow(hwndT,GW_HWNDNEXT); if (!hwndT) break; }
if (hwndT) UnloadGroupWindow(hwndT); }
LoadAllGroups(); ShowWindow(hwndMDIClient,SW_SHOW); } else { TCHAR szT[120]; WORD idGroup; HWND hwndT;
/* get the name to reload
*/ lpT = (LPTSTR) *lpwCmd++;
if (cParm == 2) { //
// Get the common group flag. The User must have Write
// access to the reload common groups.
//
if ((fCommonGrp = myatoi((LPTSTR) *lpwCmd++)) && !AccessToCommonGroups) goto DEHErrExit; } else if (AccessToCommonGroups) { //
// The default for a user with administrative rights is Common
// Groups.
//
fCommonGrp = TRUE; }
/* search for it
*/ for (hwndT = GetWindow(hwndMDIClient, GW_CHILD); hwndT; hwndT = GetWindow(hwndT, GW_HWNDNEXT)) {
/* Skip icon titles. */ if (GetWindow(hwndT, GW_OWNER)) continue;
/* Compare the group title with the request. */ pGroup = (PGROUP)GetWindowLongPtr(hwndT, GWLP_PGROUP); if (lpgd = (LPGROUPDEF)GlobalLock(pGroup->hGroup)) {
lstrcpy(szT, (LPTSTR) PTR(lpgd, lpgd->pName)); GlobalUnlock(pGroup->hGroup);
if (lstrcmpi(lpT, szT)) continue;
if ((fCommonGrp && !pGroup->fCommon) || (!fCommonGrp && pGroup->fCommon) ) continue;
/* we found the group. Unload and reload it.
*/ lstrcpy(szT,pGroup->lpKey); idGroup = pGroup->wIndex; UnloadGroupWindow(hwndT); LoadGroupWindow(szT, idGroup, fCommonGrp); break; } } if (!hwndT) goto DEHErrExit; } break; }
default: goto DEHErrExit; } }
/* 't all woiked! */ dwRet = 1;
DEHErrExit: GlobalUnlock(hCmd); GlobalFree(hCmd);
DEHErrExit1: GlobalUnlock(hString);
bInDDE = FALSE;
return dwRet; }
/*--------------------------------------------------------------------------*/ /* */ /* InitRespond() - */ /* */ /*--------------------------------------------------------------------------*/
BOOL APIENTRY InitRespond( HANDLE hWnd, WPARAM wParam, LPARAM lParam, LPTSTR szApp, LPTSTR szTopic, BOOL fBCReply // Whether or not to reply to a broadcast message.
// ie a null app string.
) { HWND hwndDDE = NULL; ATOM atom1, atom2; DWORD dwType;
atom1 = GlobalAddAtom(szApp); atom2 = GlobalAddAtom(szTopic);
if ((!LOWORD(lParam) && fBCReply) || LOWORD(lParam) == atom1) { if (!HIWORD(lParam) || HIWORD(lParam) == atom2) {
if (!lstrcmp(szApp, szProgman)) { // use Progman's main hwnd
dwType = DDE_PROGMAN; if (IsDdeConversation(hWnd, (HWND)wParam, DDE_PROGMAN)) { MPostWM_DDE_TERMINATE((HWND)wParam, hWnd); hwndDDE = CreateWindow(szProgmanDDE, NULL, WS_CHILD, 0, 0, 0, 0, hwndProgman, NULL, hAppInstance, NULL); } else { // use Progman's hwnd for the first DDE conversation
hwndDDE = hWnd; } } else if (!lstrcmp(szApp, szShell)) { if (!lstrcmp(szTopic, szAppIcon)) { if (IsDdeConversation(hWnd, (HWND)wParam, APP_ICON)) { return(TRUE); } dwType = APP_ICON; hwndDDE = CreateWindow(szAppIconDDE, NULL, WS_CHILD, 0, 0, 0, 0, hwndProgman, NULL, hAppInstance, NULL); } else if (!lstrcmp(szTopic, szAppDesc)) { if (IsDdeConversation(hWnd, (HWND)wParam, APP_DESC)) { return(TRUE); } dwType = APP_DESC; hwndDDE = CreateWindow(szAppDescDDE, NULL, WS_CHILD, 0, 0, 0, 0, hwndProgman, NULL, hAppInstance, NULL); } else if (!lstrcmp(szTopic, szAppWDir)) { if (IsDdeConversation(hWnd, (HWND)wParam, APP_WDIR)) { return(TRUE); } dwType = APP_WDIR; hwndDDE = CreateWindow(szAppWDirDDE, NULL, WS_CHILD, 0, 0, 0, 0, hwndProgman, NULL, hAppInstance, NULL); } }
//
// For compatibility reasons, allow Shell - AppProperties DDE
// connection.
//
if (!lstrcmp(szApp, szShell) && !lstrcmp(szTopic, szAppProperties) ) { // use Progman's main hwnd
dwType = DDE_PROGMAN; if (IsDdeConversation(hWnd, (HWND)wParam, DDE_PROGMAN)) { MPostWM_DDE_TERMINATE((HWND)wParam, hWnd); hwndDDE = CreateWindow(szProgmanDDE, NULL, WS_CHILD, 0, 0, 0, 0, hwndProgman, NULL, hAppInstance, NULL); } else { // use Progman's hwnd for the first DDE conversation
hwndDDE = hWnd; } }
if (hwndDDE) { SendMessage((HWND)wParam, WM_DDE_ACK, (WPARAM)hwndDDE, MAKELONG(atom1, atom2)); AddDdeConversation(hwndDDE, (HWND)wParam, dwType); return(TRUE); } } } /*
* No message sent or * Destination won't accept the ACK and so didn't delete * the atoms we provided - so we must do it. */ // GlobalDeleteAtom(atom1);
// GlobalDeleteAtom(atom2);
return(FALSE); }
/*--------------------------------------------------------------------------*/ /* */ /* GroupRequest() - */ /* */ /*--------------------------------------------------------------------------*/
VOID APIENTRY GroupRequest(HWND hWnd, HWND hwndClient, ATOM fmt, ATOM aItem) { DWORD cb; LPTSTR lpT; register HANDLE hT; register PGROUP pGroup; HANDLE hReAlloc; LPGROUPDEF lpgd;
if (fmt != CF_TEXT && fmt != CF_UNICODETEXT) { DDEFail(hWnd, hwndClient, aItem); return; }
/*sizeof (WORD) ok, as hT becomes lpT which is LPSTR*/ cb = 2 * sizeof(WORD) + 2; hT = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cb); if (!hT) { DDEFail(hWnd,hwndClient,aItem); return; }
/* Ask the client to release the data and inform him that this
* is in response to a request message. Clipboard format is * plain text. */ lpT = (LPTSTR)GlobalLock(hT); ((WORD FAR *)lpT)[0] = 3 << 12; ((WORD FAR *)lpT)[1] = CF_TEXT; ((WORD FAR *)lpT)[2] = 0; GlobalUnlock(hT);
/* Go through the list of groups appending the name of each
* group as a line in the shared memory item. */ for (pGroup=pFirstGroup; pGroup; pGroup = pGroup->pNext) { lpgd = (LPGROUPDEF)GlobalLock(pGroup->hGroup);
cb += sizeof(TCHAR) * (2 + lstrlen( (LPTSTR)PTR(lpgd, lpgd->pName) )); if (!(hReAlloc = GlobalReAlloc(hT, cb, GMEM_MOVEABLE))) { GlobalFree(hT); DDEFail(hWnd,hwndClient,aItem); return; } hT = hReAlloc;
/*sizeof (WORD) ok, as hT becomes lpT which is LPSTR*/ lpT = (LPTSTR)((LPSTR)GlobalLock(hT) + 2 * sizeof(WORD)); lpT += lstrlen(lpT); /* we've already allocated it to be large enough...
*/ //
// The title may contain ' (Common)' at the end if the group is a
// common group. So get the group title from the group itself not
// from the window title.
//
lstrcpy(lpT, (LPTSTR)PTR(lpgd, lpgd->pName)); lstrcat(lpT, TEXT("\r\n")); GlobalUnlock(pGroup->hGroup); GlobalUnlock(hT); }
if (fmt == CF_TEXT) { LPSTR lpMultiByteStr = NULL; int cchMultiByte = 0; HANDLE hMultiByte;
// convert the string to Ansi
lpT = GlobalLock(hT) ; cchMultiByte = WideCharToMultiByte(CP_ACP, 0, (LPTSTR)((LPBYTE)lpT+ 2*sizeof(WORD)), -1, lpMultiByteStr, cchMultiByte, NULL, NULL);
hMultiByte = GlobalAlloc(GMEM_MOVEABLE,(++cchMultiByte) + 2 * sizeof(WORD)); lpMultiByteStr = GlobalLock(hMultiByte);
((WORD FAR *)lpMultiByteStr)[0] = 3 << 12; ((WORD FAR *)lpMultiByteStr)[1] = CF_TEXT; WideCharToMultiByte(CP_ACP, 0, (LPTSTR)((LPBYTE)lpT+ 2*sizeof(WORD)), -1, (LPSTR)(lpMultiByteStr + 2 * sizeof(WORD)), cchMultiByte, NULL, NULL);
GlobalUnlock(hMultiByte); GlobalUnlock(hT); GlobalFree(hT); hT = hMultiByte;
} MPostWM_DDE_DATA(hwndClient, hWnd, hT, aItem); }
/*--------------------------------------------------------------------------*/ /* */ /* FindIconProp() - */ /* */ /*--------------------------------------------------------------------------*/
extern ULONG Color16Palette[]; extern ULONG Color256Palette[];
VOID APIENTRY FindIconProp(HWND hWnd, WPARAM wParam, LPARAM lParam, WORD iProp) { PGROUP pGroup; PITEM pItem; LPGROUPDEF lpgd; LPITEMDEF lpid; UINT uiMsg = WM_DDE_ACK; HANDLE hData; DDEDATA FAR * lpdd; WORD cb; NEWICONDATA FAR * lpIconData; LPBYTE lpS; LPBYTE lpD; HWND hwndT; TCHAR szCommand[MAXITEMPATHLEN+1]; TCHAR szDefDir[2 * (MAXITEMPATHLEN+1)]; ATOM aItem; // the app.'s id for which the info. is requested.
TCHAR szId[16]; //to extract the id from the atom.
DWORD dwId; PBITMAPINFOHEADER pbih, pbihNew; DWORD colors; LPVOID palette;
if (fInExec) { /* we are inside the exec call! it must have come from the
* current icon! */ pGroup = pCurrentGroup; pItem = pGroup->pItems; goto GotIt; }
/* use the mdi window list to get the z-order */ aItem = HIWORD(lParam); if (!GlobalGetAtomName(aItem, (LPTSTR)szId, 16)) goto Fail; dwId = MyAtoi((LPTSTR)szId); if (!dwId) { goto Fail; }
for (hwndT=GetWindow(hwndMDIClient, GW_CHILD); hwndT; hwndT=GetWindow(hwndT, GW_HWNDNEXT)) { if (GetWindow(hwndT, GW_OWNER)) continue;
pGroup = (PGROUP)GetWindowLongPtr(hwndT, GWLP_PGROUP);
for (pItem = pGroup->pItems; pItem; pItem = pItem->pNext) { if (pItem->dwDDEId == dwId) { goto GotIt; } } }
Fail: /* didn't find it; fail
*/ MPostDDEMsg((HWND)wParam, uiMsg, hWnd, (UINT)0, (UINT)aItem); return;
GotIt: /* from now on, we say use default instead of not me
*/ uiMsg = WM_DDE_DATA;
lpgd = LockGroup(pGroup->hwnd); if (!lpgd) goto Fail;
lpid = ITEM(lpgd,pItem->iItem);
switch (iProp) {
case APP_ICON: cb = (WORD)(sizeof(NEWICONDATA) + lpid->cbIconRes); pbih = (PBITMAPINFOHEADER)PTR(lpgd, lpid->pIconRes); if (pbih->biClrUsed == -1) { colors = (1 << (pbih ->biPlanes * pbih->biBitCount)); if (colors == 16 || colors == 256) { cb += (WORD)(colors * sizeof(RGBQUAD)); } } break;
case APP_DESC: cb = (WORD)(sizeof(DDEDATA) + sizeof(TCHAR)*lstrlen((LPTSTR) PTR(lpgd, lpid->pName))); break;
case APP_WDIR: GetItemCommand(pGroup, pItem, szCommand, szDefDir); cb = (WORD)(sizeof(DDEDATA) + sizeof(TCHAR)*lstrlen(szDefDir)); break;
default: goto Fail; }
hData = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT, (DWORD)cb); if (!hData) { UnlockGroup(pGroup->hwnd); goto Fail; }
lpdd = (DDEDATA FAR *)GlobalLock(hData); if (!lpdd) { GlobalFree(hData); UnlockGroup(pGroup->hwnd); goto Fail; } lpdd->fResponse = TRUE; lpdd->fRelease = TRUE; lpdd->cfFormat = CF_TEXT;
switch (iProp) { case APP_ICON: if ((short)lpid->cbIconRes <= 0) { // This icon is toast.
GlobalUnlock(hData); UnlockGroup(pGroup->hwnd); goto Fail; }
lpIconData = (NEWICONDATA FAR *)lpdd;
lpIconData->dwResSize = (DWORD)lpid->cbIconRes; //lpIconData->dwVer = lpid->dwIconVer;
lpIconData->dwVer = (lpid->wIconVer == 2) ? 0x00020000 : 0x00030000;
lpD = (LPBYTE)&(lpIconData->iResource); lpS = (LPBYTE)PTR(lpgd, lpid->pIconRes); cb = lpid->cbIconRes; if ((pbih->biClrUsed == -1) && (colors == 16 || colors == 32)) { if (colors == 16) { palette = Color16Palette; } else if (colors == 256) { palette = Color256Palette; }
pbihNew = (PBITMAPINFOHEADER)lpD; RtlCopyMemory(pbihNew, pbih, sizeof( *pbih )); pbihNew->biClrUsed = 0; RtlCopyMemory((pbihNew+1), palette, colors * sizeof(RGBQUAD)); RtlCopyMemory((PCHAR)(pbihNew+1) + (colors * sizeof(RGBQUAD)), (pbih+1), lpid->cbIconRes - sizeof(*pbih) ); } else { while (cb--) { *lpD++ = *lpS++; } }
break;
case APP_DESC: lstrcpy((LPTSTR)lpdd->Value,(LPTSTR) PTR(lpgd, lpid->pName)); break;
case APP_WDIR: lstrcpy((LPTSTR)lpdd->Value,szDefDir); break; }
GlobalUnlock(hData); UnlockGroup(pGroup->hwnd);
if (!MPostWM_DDE_DATA((HWND)wParam, hWnd, hData, (ATOM)aItem)){ GlobalFree(hData); } }
/*--------------------------------------------------------------------------*/ /* */ /* FindIconPath() - */ /* In NT groups the icon path is not stored when it is not specified by */ /* the user when the item is created. For DDE requests on groups, the */ /* icon path needs to be returned. This function will determine the */ /* icon path the way it first find the icon. */ /* 9/17/93 JOhannec
/* */ /*--------------------------------------------------------------------------*/
VOID FindIconPath( LPTSTR szPathField, LPTSTR szDirField, LPTSTR szIconPath ) { TCHAR szIconExe[MAX_PATH]; TCHAR szTemp[MAX_PATH]; HICON hIcon; WORD wIconIndex; WORD wIconId;
lstrcpy(szIconExe, szPathField); DoEnvironmentSubst(szIconExe, CharSizeOf(szIconExe)); StripArgs(szIconExe); TagExtension(szIconExe, sizeof(szIconExe)); if (*szIconExe == TEXT('"') && *(szIconExe + lstrlen(szIconExe)-1) == TEXT('"')) { SheRemoveQuotes(szIconExe); }
//
// if it's a relative path, extractassociatedicon and LoadLibrary don't
// handle that so find the executable first
//
SetCurrentDirectory(szOriginalDirectory); FindExecutable(szIconExe, szDirField, szTemp); if (*szTemp) { lstrcpy(szIconExe, szTemp); TagExtension(szIconExe, sizeof(szIconExe)); if (*szIconExe == TEXT('"') && *(szIconExe + lstrlen(szIconExe)-1) == TEXT('"')) { SheRemoveQuotes(szIconExe); } } else { *szIconExe = 0; // Use a dummy value so no icons will be found
// and progman's item icon will be used instead
// This is to make moricons.dll item icon be the
// right one. -johannec 6/4/93
} //
// reset the current directory to progman's working directory i.e. Windows directory
//
SetCurrentDirectory(szWindowsDirectory);
wIconIndex = 0; hIcon = ExtractAssociatedIconEx(hAppInstance, szIconExe, &wIconIndex, &wIconId); if (hIcon) DestroyIcon(hIcon);
lstrcpy(szIconPath, szIconExe); }
/*--------------------------------------------------------------------------*/ /* */ /* AddStringToSeg() - */ /* */ /*--------------------------------------------------------------------------*/ BOOL APIENTRY AddStringToSeg(LPHANDLE lphT, LPINT lpcb, LPTSTR lpsz, WORD wT, BOOL fCR) { TCHAR szT[10]; INT cb; LPTSTR lp; HANDLE hReAlloc;
if (!lpsz) { wsprintf(szT,TEXT("%d"),wT); lpsz = szT; wT = (WORD)0; }
cb = sizeof(TCHAR) * (lstrlen(lpsz) + (wT ? 2 : 0) + (fCR ? 2 : 1)); if (!(hReAlloc = GlobalReAlloc(*lphT,*lpcb+cb,GMEM_MOVEABLE|GMEM_ZEROINIT))) { GlobalFree(*lphT); return FALSE; } else { *lphT = hReAlloc; }
lp = (LPTSTR)((LPSTR)GlobalLock(*lphT) + *lpcb - 2); // this is to go before the null byte
if (wT) *lp++ = TEXT('"');
lstrcpy(lp,lpsz); lp += lstrlen(lp); if (wT) *lp++ = TEXT('"');
if (fCR) { *lp++ = TEXT('\r'); *lp++ = TEXT('\n'); } else *lp++ = TEXT(','); *lp = 0; GlobalUnlock(*lphT);
*lpcb += cb;
return TRUE; }
/*--------------------------------------------------------------------------*/ /* */ /* DumpGroup() - */ /* */ /*--------------------------------------------------------------------------*/ VOID APIENTRY DumpGroup(HWND hwnd, ATOM aName, HWND hwndConv, WORD cfFormat) { HWND hwndGroup; PGROUP pGroup; PITEM pItem; LPGROUPDEF lpgd; LPITEMDEF lpid; WORD i; INT cb; HANDLE hT; LPTSTR lpT; INT state; BOOL fActivated;
if (cfFormat != CF_TEXT && cfFormat != CF_UNICODETEXT) goto Fail;
for (hwndGroup = GetWindow(hwndMDIClient,GW_CHILD); hwndGroup; hwndGroup = GetWindow(hwndGroup,GW_HWNDNEXT)) { if (GetWindow(hwndGroup,GW_OWNER)) continue;
lpgd = LockGroup(hwndGroup); if (!lpgd) goto Fail;
if (aName == GlobalFindAtom((LPTSTR) PTR(lpgd, lpgd->pName))) goto FoundGroup; UnlockGroup(hwndGroup); }
Fail: #ifdef ORGCODE
DDEFail(hwnd,hwndConv,MAKELONG(cfFormat,aName)); #else
DDEFail(hwnd, hwndConv, aName); #endif
return;
FoundGroup: pGroup = (PGROUP)GetWindowLongPtr(hwndGroup,GWLP_PGROUP);
/*sizeof (WORD) ok, as hT becomes lpT which is LPSTR*/ cb = 2 * sizeof(WORD) + 2; hT = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cb); if (!hT) goto Fail;
/* Ask the client to release the data and inform him that this
* is in response to a request message. Clipboard format is * plain text. */ lpT = (LPTSTR)GlobalLock(hT); ((WORD FAR *)lpT)[0] = 3 << 12; ((WORD FAR *)lpT)[1] = CF_TEXT; ((WORD FAR *)lpT)[2] = 0; GlobalUnlock(hT);
/* the first line is group properties
*/ if (!AddStringToSeg(&hT,&cb,(LPTSTR) PTR(lpgd, lpgd->pName),TRUE,FALSE)) goto Fail;
#if 1
// don't allow apps to know the group key.
//
// change 2-21-93 johannec
// for compatibilty reasons we must privide the group filename which
// doesn't mean anything in NT so we provide the key name instad.
if (!AddStringToSeg(&hT,&cb,pGroup->lpKey, FALSE, FALSE)) goto Fail; #endif
/* put the number of items in
*/ for (i = 0, pItem = pGroup->pItems; pItem; pItem = pItem->pNext) i++;
#if 1
if (!AddStringToSeg(&hT,&cb,NULL,i,FALSE)) goto Fail;
// Return the window state as a SW_ value.
// REVIEW not all SW_ values are supported.
// It would be nice if there was some way to query a SW_ value
// but I guess it would too much to ask for windows to be even remotely
// orthogonal. I don't know who "designed" the Windows API but it
// really is the worst windowing system I have ever used.
// Luckily orthogonality doesn't affect stock prices :-)
state = SW_SHOWNORMAL;
if (pGroup == pCurrentGroup) { fActivated = TRUE; } else { fActivated = FALSE; }
if (IsZoomed(hwndGroup)) { // Maxed.
state = SW_SHOWMAXIMIZED; } else if (IsIconic(hwndGroup)) { // Minned.
if(fActivated) state = SW_SHOWMINIMIZED; else state = SW_SHOWMINNOACTIVE; } else { // It's normal.
if(fActivated) state = SW_SHOWNORMAL; else state = SW_SHOWNOACTIVATE; }
// Give info on the state.
if (!AddStringToSeg(&hT,&cb,NULL,(WORD)state, FALSE)) goto Fail; #else
if (!AddStringToSeg(&hT,&cb,NULL,i,FALSE)) goto Fail; #endif
if (!AddStringToSeg(&hT,&cb,NULL,(WORD)pGroup->fCommon,TRUE)) goto Fail;
/* each additional line is an item
*/ for (pItem = pGroup->pItems; pItem; pItem = pItem->pNext) {
lpid = ITEM(lpgd,pItem->iItem);
/* name
*/ if (!AddStringToSeg(&hT, &cb, (LPTSTR) PTR(lpgd, lpid->pName), TRUE, FALSE)) goto Fail;
/* command line and default directory
*/ GetItemCommand(pGroup, pItem, szPathField, szDirField); if (!AddStringToSeg(&hT, &cb, szPathField, TRUE, FALSE)) goto Fail; if (!AddStringToSeg(&hT, &cb, szDirField, FALSE, FALSE)) goto Fail;
/* icon path
*/ if (!*(LPTSTR)PTR(lpgd, lpid->pIconPath)) { FindIconPath(szPathField, szDirField, szIconPath); } else { lstrcpy(szIconPath, (LPTSTR) PTR(lpgd, lpid->pIconPath)); } if (!AddStringToSeg(&hT, &cb, szIconPath, FALSE, FALSE)) goto Fail;
/* x-y coordinates
*/ if (!AddStringToSeg(&hT, &cb, NULL, (WORD)pItem->rcIcon.left, FALSE)) goto Fail;
if (!AddStringToSeg(&hT, &cb, NULL, (WORD)pItem->rcIcon.top, FALSE)) goto Fail;
/* icon, hotkey, fminimize
*/ if ((SHORT)lpid->wIconIndex >= 0) { //
// apps requesting group info are expecting icon index not icon id.
//
if (!AddStringToSeg(&hT, &cb, NULL, lpid->wIconIndex,FALSE)) goto Fail; } else { if (!AddStringToSeg(&hT, &cb, NULL, lpid->iIcon, FALSE)) goto Fail; }
if (!AddStringToSeg(&hT,&cb,NULL,GroupFlag(pGroup,pItem,(WORD)ID_HOTKEY),FALSE)) goto Fail;
if (!AddStringToSeg(&hT,&cb,NULL,GroupFlag(pGroup,pItem,(WORD)ID_MINIMIZE),FALSE)) goto Fail;
if (!AddStringToSeg(&hT,&cb,NULL,GroupFlag(pGroup,pItem,(WORD)ID_NEWVDM),TRUE)) goto Fail; }
#ifdef ORGCODE
PostMessage(hwndConv, WM_DDE_DATA, hwnd, MAKELONG(hT,cfFormat)); #else
if (cfFormat == CF_TEXT) { LPSTR lpMultiByteStr = NULL; int cchMultiByte = 0; HANDLE hMultiByte;
// convert the string to Ansi
lpT = GlobalLock(hT) ; cchMultiByte = WideCharToMultiByte(CP_ACP, 0, (LPTSTR)((LPBYTE)lpT+ 2*sizeof(WORD)), -1, lpMultiByteStr, cchMultiByte, NULL, NULL);
hMultiByte = GlobalAlloc(GMEM_MOVEABLE,(++cchMultiByte) + 2 * sizeof(WORD)); lpMultiByteStr = GlobalLock(hMultiByte);
((WORD FAR *)lpMultiByteStr)[0] = 3 << 12; ((WORD FAR *)lpMultiByteStr)[1] = CF_TEXT; WideCharToMultiByte(CP_ACP, 0, (LPTSTR)((LPBYTE)lpT+ 2*sizeof(WORD)), -1, (LPSTR)(lpMultiByteStr + 2 * sizeof(WORD)), cchMultiByte, NULL, NULL);
GlobalUnlock(hMultiByte); GlobalUnlock(hT); GlobalFree(hT); hT = hMultiByte;
} MPostWM_DDE_DATA(hwndConv, hwnd, hT, (ATOM)aName); #endif
}
/*--------------------------------------------------------------------------*/ /* */ /* DDEMsgProc() - */ /* */ /*--------------------------------------------------------------------------*/
LRESULT APIENTRY DDEMsgProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) { switch (wMsg) { // should go in ProgmanWndProc
case WM_DDE_INITIATE: //
// HACK: returning 1 if the WM_DDE_ACK was sent successfully in
// InitRespond is NOT part of the DDE Protocol BUT for backward
// compatability with WIndows3.0 and 3.1 this solves
// some problems with WOW apps' setup.
//
#ifdef DEBUG_PROGMAN_DDE
{ TCHAR szDebug[300];
wsprintf (szDebug, TEXT("%d PROGMAN: Received WM_DDE_INITIATE\r\n"), GetTickCount()); OutputDebugString(szDebug); } #endif
if (InitRespond(hWnd,wParam,lParam,szShell,szAppIcon, TRUE)) return(1L); if (InitRespond(hWnd,wParam,lParam,szShell,szAppDesc, TRUE)) return(1L); if (InitRespond(hWnd,wParam,lParam,szShell,szAppWDir, TRUE)) return(1L); // InitRespond(hWnd,wParam,lParam,szShell,szSystem, TRUE);
if (InitRespond(hWnd,wParam,lParam,szProgman,szProgman, FALSE)) { #ifdef DEBUG_PROGMAN_DDE
{ TCHAR szDebug[300];
wsprintf (szDebug, TEXT("%d PROGMAN: Received WM_DDE_INITIATE. return 1\r\n"), GetTickCount()); OutputDebugString(szDebug); } #endif
return(1L); } //
// For compatibility reasons, allow Shell - AppProperties DDE
// connection
//
if (InitRespond(hWnd,wParam,lParam,szShell,szAppProperties, TRUE)) return(1L);
#ifdef DEBUG_PROGMAN_DDE
{ TCHAR szDebug[300];
wsprintf (szDebug, TEXT("%d PROGMAN: Received WM_DDE_INITIATE. FAILED\r\n"), GetTickCount()); OutputDebugString(szDebug); } #endif
break;
case WM_DDE_REQUEST: { ATOM fmt; ATOM aItem;
fmt = GET_WM_DDE_REQUEST_FORMAT(wParam, lParam); aItem = GET_WM_DDE_REQUEST_ITEM(wParam, lParam); if (aItem == GlobalFindAtom(szProgman) || aItem == GlobalFindAtom(szGroupList)) { GroupRequest(hWnd, (HWND)wParam, fmt, aItem); } else DumpGroup(hWnd, aItem, (HWND)wParam, fmt); DDEFREE(WM_DDE_REQUEST, lParam); break; }
case WM_DDE_EXECUTE: { HANDLE hCommands; WORD wStatus; DWORD ret; LPSTR lpCommands ; HLOCAL hloc ; HLOCAL hlocTemp ; int cchMultiByte ; LPWSTR lpWideCharStr = NULL ; int cchWideChar = 0 ; BOOL bIsWindowUnicode ; UnpackDDElParam(WM_DDE_EXECUTE, lParam, NULL, (PUINT_PTR)&hCommands);
// was the sending window a unicode app?
bIsWindowUnicode=IsWindowUnicode((HWND)wParam) ; if (!bIsWindowUnicode) { // convert the string to unicode
lpCommands = GlobalLock(hCommands) ; cchMultiByte=MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,lpCommands, -1,lpWideCharStr,cchWideChar) ;
hloc = GlobalAlloc(GMEM_MOVEABLE,(++cchMultiByte)*sizeof(TCHAR)) ; lpWideCharStr = GlobalLock(hloc) ;
MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,lpCommands, -1,lpWideCharStr,cchMultiByte) ;
GlobalUnlock(hloc) ; GlobalUnlock(hCommands) ; hlocTemp = hCommands; hCommands = hloc ; }
if (ret = ExecuteHandler(hCommands)) { wStatus = 0x8000; } else { wStatus = 0x0000; } if (!bIsWindowUnicode) { hCommands = hlocTemp; GlobalFree(hloc) ; }
MPostWM_DDE_EXECACK((HWND)wParam, hWnd, wStatus, hCommands); if (ret == 2) { // Exit command was executed
MPostWM_DDE_TERMINATE((HWND)wParam, hWnd); PostMessage(hwndProgman, WM_CLOSE, 0, 0L); } // DDEFREE(WM_DDE_EXECUTE, lParam); // executes arn't really packed.
break; }
case WM_DDE_TERMINATE: #ifdef ORGCODE
SendMessage(wParam, WM_DDE_TERMINATE, (WPARAM)hWnd, lParam); #else
RemoveDdeConversation(hWnd, (HWND)wParam, DDE_PROGMAN); MPostWM_DDE_TERMINATE((HWND)wParam, hWnd); // DDEFREE(WM_DDE_TERMINATE, lParam); // terminates arn't packed
#endif
if (hWnd != hwndProgman) { DestroyWindow (hWnd); } break;
case WM_DDE_ACK: DDEFREE(WM_DDE_ACK, lParam); break;
/* All other DDE messages are unsupported. */ case WM_DDE_DATA: case WM_DDE_ADVISE: case WM_DDE_UNADVISE: case WM_DDE_POKE: #ifdef ORGCODE
DDEFail(hWnd,wParam,lParam); #else
{ UINT_PTR uiHi;
UnpackDDElParam(wMsg, lParam, NULL, &uiHi); DDEFail(hWnd, (HWND)wParam, (ATOM)uiHi); DDEFREE(wMsg, lParam); } #endif
break;
default: return DefWindowProc(hWnd,wMsg,wParam,lParam); } return(0L); }
/*--------------------------------------------------------------------------*/ /* */ /* AppIconDDEMsgProc() - */ /* */ /* Application = "Shell" */ /* Topic = "AppIcon" */ /* */ /*--------------------------------------------------------------------------*/
LRESULT APIENTRY AppIconDDEMsgProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) { switch (wMsg) { case WM_DDE_REQUEST: FindIconProp(hWnd, wParam, lParam, APP_ICON); DDEFREE(WM_DDE_REQUEST, lParam); break;
case WM_DDE_TERMINATE: RemoveDdeConversation(hWnd, (HWND)wParam, APP_ICON); MPostWM_DDE_TERMINATE((HWND)wParam, hWnd); DDEFREE(WM_DDE_TERMINATE, lParam); DestroyWindow(hWnd); break;
default: return DDEMsgProc(hWnd, wMsg, wParam, lParam); } return 0L; }
/*--------------------------------------------------------------------------*/ /* */ /* AppDescriptionDDEMsgProc() - */ /* */ /* Application = "Shell" */ /* Topic = "AppDescription" */ /* */ /*--------------------------------------------------------------------------*/
LRESULT APIENTRY AppDescriptionDDEMsgProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) { switch (wMsg) { case WM_DDE_REQUEST: FindIconProp(hWnd, wParam, lParam, APP_DESC); DDEFREE(WM_DDE_REQUEST, lParam); break;
case WM_DDE_TERMINATE: RemoveDdeConversation(hWnd, (HWND)wParam, APP_DESC); PostMessage((HWND)wParam, WM_DDE_TERMINATE, (WPARAM)hWnd, 0L); DestroyWindow(hWnd); break;
default: return DDEMsgProc(hWnd, wMsg, wParam, lParam); } return 0L; }
/*--------------------------------------------------------------------------*/ /* */ /* AppWorkingDirDDEMsgProc() - */ /* */ /* Application = "Shell" */ /* Topic = "AppWorkingDir" */ /* */ /*--------------------------------------------------------------------------*/
LRESULT APIENTRY AppWorkingDirDDEMsgProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) { switch (wMsg) { case WM_DDE_REQUEST: FindIconProp(hWnd, wParam, lParam, APP_WDIR); DDEFREE(WM_DDE_REQUEST, lParam); break;
case WM_DDE_TERMINATE: RemoveDdeConversation(hWnd, (HWND)wParam, APP_WDIR); MPostWM_DDE_TERMINATE((HWND)wParam, hWnd); DDEFREE(WM_DDE_TERMINATE, lParam); DestroyWindow(hWnd); break;
default: return DDEMsgProc(hWnd, wMsg, wParam, lParam); } return 0L; }
VOID APIENTRY RegisterDDEClasses(HANDLE hInstance) { WNDCLASS wc;
wc.style = 0; wc.lpfnWndProc = AppIconDDEMsgProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = NULL; wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = szAppIconDDE;
if (!RegisterClass(&wc)) bAppIconDDE = FALSE;
wc.lpfnWndProc = AppDescriptionDDEMsgProc; wc.lpszClassName = szAppDescDDE;
if (!RegisterClass(&wc)) bAppDescDDE = FALSE;
wc.lpfnWndProc = AppWorkingDirDDEMsgProc; wc.lpszClassName = szAppWDirDDE;
if (!RegisterClass(&wc)) bAppWDirDDE = FALSE;
wc.lpfnWndProc = DDEMsgProc; wc.lpszClassName = szProgmanDDE;
if (!RegisterClass(&wc)) bProgmanDDE = FALSE;
InitDdeConversationStruct();
}
|