home *** CD-ROM | disk | FTP | other *** search
- /*static char *SCCSID = "@(#)easea.c 6.7 92/02/18";*/
- /*==============================================================*\
- * *
- * EASEA.C - sample PM application *
- * (C) Copyright IBM Corporation 1992. *
- *--------------------------------------------------------------*
- * This module contains subroutines for eas.c that *
- * specifically deal with the manipulation of EAs. *
- * *
- *--------------------------------------------------------------*
- * Procedures in this file: *
- * AddEA() Handles the Add button press *
- * QueryEAs() Reads in all the EAs associated with a file
- * CheckEAIntegrity()Checks an EA buffer to see if it is valid*
- * Free_FEAList() Deallocates memory associated with EA list
- * LookupEAType() Gets an offset into table for an EA type *
- * DeleteCurEA() Deletes the highlighted EA *
- * CurEAType() Returns EA Type given a HoldFEA ptr *
- * GetUSHORT() Returns nth USHORT in ->aValue *
- * WriteEAs() Updates EAs state on the disk *
- * EditEAValue() Handles editing a given EA ( m-m EAs) *
- * EAExists() Determines if the given EA Name exists *
- * ChangeName() Handles the change of an EA's name *
- * MultiTypeIndex() Gets a specific field in a m-m structure *
- * EAValueString() Returns a representational string for EA*
- * MultiAdd() Handles addition of a field for m-m *
- \*==============================================================*/
- /*--------------------------------------------------------------*\
- * Include files, macros, defined constants, and externs *
- \*--------------------------------------------------------------*/
- #include "eas.h"
-
- extern EADATA ConvTable[EATABLESIZE];
-
- /****************************************************************\
- * *
- * Name: AddEA(hwnd) *
- * *
- * Purpose: This routine handles the addition of a new EA to *
- * the linked list. *
- * *
- * Usage : *
- * *
- * Method : Routine does NOT do full memory error trapping and *
- * the insert message to l-box is not error checked. *
- * *
- * Returns: TRUE if the EA is successfully added. *
- * *
- \****************************************************************/
- BOOL AddEA(HWND hwnd)
- {
- HOLDFEA *pFEA=pHoldFEA; /* Points to the beginning of the EA list */
- HOLDFEA *pNewFEA=NULL; /* Used to temporarily hold the new EA */
- PASSDATA PData;
-
- if(!FILE_ISOPEN)
- {
- MessageBox(hwnd, IDMSG_NOFILEOPEN, "Error !",
- MB_OK | MB_ERROR, TRUE);
- return(FALSE);
- }
- if(!WinDlgBox(HWND_DESKTOP, /* get new EA name and type */
- hwnd,
- AddEAProc,
- '\0',
- IDD_ADDEA,
- '\0'))
- return(FALSE); /* they said cancel */
-
- GetMem((PPVOID)&pNewFEA, sizeof(HOLDFEA));/* Allocate space for new EA struct */
-
- pNewFEA->cbName = (CHAR) strlen(szEAName); /* Fill in new structure */
- pNewFEA->cbValue= 0;
- pNewFEA->fEA = 0; /* Need bit NOT set */
- /* Name returned in szEAName */
- GetMem((PPVOID)&pNewFEA->szName, pNewFEA->cbName+1);
- strcpy(pNewFEA->szName,strupr(szEAName));
- pNewFEA->aValue = '\0';
- pNewFEA->next = '\0';
-
- if(pHoldFEA == '\0') /* It's the first EA for the file */
- pHoldFEA = pNewFEA;
- else /* Add EA to the end of the linked list */
- {
- while(pFEA->next)
- pFEA = pFEA->next;
- pFEA->next = pNewFEA;
- }
- PData.Point = (CHAR *) pNewFEA; /* Setup user data for call */
- PData.cbMulti = 0; /* to edit of the name and */
- PData.usMultiOffset = 0; /* EA Value */
-
- if(!EditEAValue(hwnd,&PData)) /* They canceled the edit */
- {
- if(pFEA) /* It's not the only EA */
- pFEA->next = '\0'; /* Disconnect the partial new EA */
- else
- pHoldFEA = '\0'; /* The new EA was the first one */
-
- FreeMem(pNewFEA->szName);
- FreeMem(pNewFEA);
-
- return(FALSE);
- }
- WinSendDlgItemMsg(hwnd, IDD_WINLBOX, LM_INSERTITEM,/* Insert name in L-Box */
- MPFROM2SHORT(LIT_END,0),
- MPFROMP(pNewFEA->szName));
- return(TRUE);
- }
-
- /****************************************************************\
- * *
- * Name: QueryEAs(pszPath) *
- * *
- * Purpose: Call DOS to Query a file's EA names and values. *
- * *
- * Usage: *
- * *
- * Method : Routine does NOT do full memory error trapping. *
- * NOTE: This routine does NOT prevent other *
- * processes from accessing the file's EAs while it is*
- * reading them in, or while the program is editing *
- * them. *
- * *
- * Returns: TRUE if it successfully reads in the EAs. Upon exit*
- * , globalp HoldFEA points to a linked list of the *
- * EAs for the current file. *
- * *
- \****************************************************************/
- BOOL QueryEAs(CHAR *pszPath)
- {
- CHAR *pAllocc=NULL; /* Holds the FEA struct returned by DosEnumAttribute */
- /* used to create the GEA2LIST for DosQueryPathInfo */
- CHAR *pBigAlloc=NULL; /* Temp buffer to hold each EA as it is read in */
- USHORT cbBigAlloc=0; /* Size of buffer */
-
- ULONG ulEntryNum = 1; /* count of current EA to read (1-relative) */
- ULONG ulEnumCnt; /* Number of EAs for Enum to return, always 1 */
-
- HOLDFEA *pLastIn=0; /* Points to last EA added, so new EA can link */
- HOLDFEA *pNewFEA=NULL; /* Struct to build the new EA in */
-
- FEA2 *pFEA; /* Used to read from Enum's return buffer */
- GEA2LIST *pGEAList;/*Ptr used to set up buffer for DosQueryPathInfo call */
- EAOP2 eaopGet; /* Used to call DosQueryPathInfo */
- /* Allocate enough room for any GEA List */
- GetMem((PPVOID)&pAllocc, MAX_GEA);
- pFEA = (FEA2 *) pAllocc; /* pFEA always uses pAlloc buffer */
-
- pHoldFEA = '\0'; /* Reset the pointer for the EA linked list */
-
- while(TRUE) /* Loop continues until there are no more EAs */
- {
- ulEnumCnt = 1; /* Only want to get one EA at a time */
- if(DosEnumAttribute(Ref_ASCIIZ, /* Read into pAlloc Buffer */
- pszPath, /* Note that this does not */
- ulEntryNum, /* get the aValue field, */
- pAllocc, /* so DosQueryPathInfo must*/
- MAX_GEA, /* be called to get it. */
- &ulEnumCnt,
- (LONG) GetInfoLevel1))
- break; /* There was some sort of error */
-
- if(ulEnumCnt != 1) /* All the EAs have been read */
- break;
-
- ulEntryNum++;
-
- GetMem((PPVOID)&pNewFEA, sizeof(HOLDFEA));
-
- if (pNewFEA == '\0') /* Out of memory */
- {
- FreeMem(pAllocc);
- Free_FEAList(pHoldFEA,pDelList);
- return (FALSE);
- }
-
- pNewFEA->cbName = pFEA->cbName; /* Fill in the HoldFEA structure */
- pNewFEA->cbValue= pFEA->cbValue;
- pNewFEA->fEA = pFEA->fEA;
- pNewFEA->next = '\0';
-
- GetMem((PPVOID)&pNewFEA->szName, pFEA->cbName +1); /* Allocate for 2 arrays */
- GetMem((PPVOID)&pNewFEA->aValue, pFEA->cbValue);
-
- if (!pNewFEA->szName || !pNewFEA->aValue) /* Out of memory */
- {
- if(pNewFEA->szName)
- FreeMem(pNewFEA->szName);
- if(pNewFEA->aValue)
- FreeMem(pNewFEA->aValue);
-
- FreeMem(pAllocc);
- FreeMem(pNewFEA);
-
- Free_FEAList(pHoldFEA,pDelList);
- return (FALSE);
- }
- strcpy(pNewFEA->szName,pFEA->szName); /* Copy in EA Name */
-
- cbBigAlloc = sizeof(FEA2LIST) + pNewFEA->cbName+1 +
- pNewFEA->cbValue;
- GetMem((PPVOID)&pBigAlloc, cbBigAlloc);
- if (pBigAlloc == '\0')
- {
- FreeMem(pNewFEA->szName);
- FreeMem(pNewFEA->aValue);
- FreeMem(pAllocc);
- FreeMem(pNewFEA);
- Free_FEAList(pHoldFEA,pDelList);
- return (FALSE);
- }
-
- pGEAList = (GEA2LIST *) pAllocc; /* Set up GEAList structure */
-
- pGEAList->cbList = sizeof(GEA2LIST) + pNewFEA->cbName; /* +1 for NULL */
- pGEAList->list[0].oNextEntryOffset = 0L;
- pGEAList->list[0].cbName = pNewFEA->cbName;
- strcpy(pGEAList->list[0].szName,pNewFEA->szName);
-
- eaopGet.fpGEA2List = (GEA2LIST FAR *) pAllocc;
- eaopGet.fpFEA2List = (FEA2LIST FAR *) pBigAlloc;
-
- eaopGet.fpFEA2List->cbList = cbBigAlloc;
-
- DosQueryPathInfo(pszPath, /* Get the complete EA info */
- FIL_QUERYEASFROMLIST,
- (PVOID) &eaopGet,
- sizeof(EAOP2));
- memcpy(pNewFEA->aValue, /* Copy the value to HoldFEA */
- pBigAlloc+sizeof(FEA2LIST)+pNewFEA->cbName,
- pNewFEA->cbValue);
-
- FreeMem(pBigAlloc); /* Release the temp Enum buffer */
-
- if(!CheckEAIntegrity(pNewFEA->aValue,pNewFEA->cbValue)) /* Bad EA */
- {
- FreeMem(pNewFEA->szName);
- FreeMem(pNewFEA->aValue);
- FreeMem(pNewFEA);
- continue; /* Don't add this EA to linked list */
- }
-
- if(pHoldFEA == '\0') /* If first EA, set pHoldFEA */
- pHoldFEA = pNewFEA;
- else /* Otherwise, add to end of list */
- pLastIn->next = pNewFEA;
-
- pLastIn = pNewFEA; /* Update the end of the list */
- }
- FreeMem(pAllocc); /* Free up the GEA buf for DosEnum */
- return (TRUE);
- }
-
-
- /****************************************************************\
- * *
- * Function name: CheckEAIntegrity(aBuf, cbBuf) *
- * *
- * Returns: TRUE if the buffer is a valid EA structure. *
- * *
- * Purpose: This routine checks the integrity of the passed EA *
- * buffer by seeing if there are any non-standard EA *
- * types, or bad data that isn't sized correctly. *
- * Usage : *
- * Method : Routine uses MultiTypeIndex() to check m-m type EAs*
- * since they are potentially recursive. However, this*
- * may not be a good idea if the m-m EA is severly *
- * corrupted because it may cause MTI() to attempt a *
- * read from protected memory. Routine does NOT modify*
- * the buffer under any circumstance. *
- * *
- * Returns: TRUE if the buffer is a valid EA structure. *
- * *
- \****************************************************************/
- BOOL CheckEAIntegrity(CHAR *aBuf, ULONG cbBuf)
- {
- USHORT *pusPtr = (USHORT *) aBuf;
- USHORT usOffset;
- CHAR *aEndPtr;
-
- usOffset = LookupEAType(*pusPtr); /* Get the EA type */
-
- switch(ConvTable[usOffset].usFldType)
- {
- case IDD_LPDATA:
- pusPtr++;
- if(*pusPtr + 2*sizeof(USHORT) == cbBuf)
- return TRUE;
- else
- return FALSE;
-
- case IDD_MULTILIST:
- if(*pusPtr == EA_MVMT)
- {
- pusPtr += 2;
-
- /* This checks where the end of the m-m list ends to determine
- the size of the EA. This is probably not good if the EA is
- badly corrupted and it points to protected memory */
-
- aEndPtr = MultiTypeIndex(aBuf,*pusPtr);
- if(aEndPtr - aBuf == (CHAR) cbBuf)
- return TRUE;
- else
- return FALSE;
- }
- else /* Single type, multi-value is not yet implemented */
- {
- return TRUE;
- }
- default:
- return FALSE;
- }
- return TRUE;
- }
-
- /****************************************************************\
- * *
- * Name: Free_FEAList(pFEA, pDList) *
- * *
- * Purpose: This routine frees up the current list of EAs by *
- * deallocating the space used by the szName and *
- * aValue fields, then deallocating the HoldFEA struct*
- * Next, it deletes the EAName space, then the *
- * DeleteList structure. *
- * Usage : *
- * Method: Note that EAS always passes in pHoldFEA and *
- * pDelList which is unnecessary since they are global*
- * pointers;however, this is done to make the routine *
- * more flexible by allowing multiple linked lists to *
- * exist. *
- * *
- * Returns: VOID. The two linked lists passed in are cleaned *
- * out though. *
- * *
- \****************************************************************/
- VOID Free_FEAList(HOLDFEA *pFEA, DELETELIST *pDList)
- {
- HOLDFEA *next; /* Holds the next field since we free the structure */
- /* before reading the current next field */
- DELETELIST *Dnext; /* Same purpose as *next */
-
- while(pFEA)
- {
- next = pFEA->next;
- if(pFEA->szName) /* Free if non-NULL name */
- FreeMem(pFEA->szName);
- if(pFEA->aValue) /* Free if non-NULL value */
- FreeMem(pFEA->aValue);
-
- FreeMem(pFEA); /* Free HoldFEA struct */
- pFEA = next;
- }
- while(pDList)
- {
- Dnext = pDList->next;
- if(pDList->EAName)
- FreeMem(pDList->EAName);
- FreeMem(pDList);
- pDList = Dnext;
- }
- return;
- }
-
- /****************************************************************\
- * *
- * Name: LookupEAType(usType) *
- * *
- * Purpose: This routine takes EA type and returns an offset *
- * into ConvTable which points to an entry that *
- * describes the type passed in. *
- * *
- * Usage: *
- * Method: *
- * *
- * Returns: An offset into the ConvTable to the appropriate *
- * entry. If no match is found, the return value *
- * points to the last entry, non-conventional format. *
- * *
- \****************************************************************/
- ULONG LookupEAType(ULONG usType)
- {
- USHORT cnt;
-
- for(cnt=0;cnt<EATABLESIZE-1;cnt++)
- if(ConvTable[cnt].usPrefix == usType)
- return(cnt);
- return(cnt);
- }
-
- /****************************************************************\
- * *
- * Name: DeleteCurEA(hwnd) *
- * *
- * Purpose: This routine removes in memory the currently *
- * highlighted EA from the EA list. It places the *
- * deleted EA in the global pDelList linked list. *
- * *
- * Usage: This routine is called by MainDlgProc when DELETE *
- * button selected. *
- * *
- * Method: The memory allocation routines are NOT fully error *
- * trapped. *
- * *
- * Returns: VOID. Removes one item from global pHoldFEA list *
- * and adds one to global pDelList. *
- * *
- \****************************************************************/
- VOID DeleteCurEA(HWND hwnd)
- {
- HOLDFEA *pFEA,*pFEAPrev;
- DELETELIST *pDL=NULL, *pDLcnt;/*Utility ptrs for manipulating the Del list*/
- SHORT sOffset;
- SHORT i;
-
- if(!FILE_ISOPEN)
- {
- MessageBox(hwnd, IDMSG_ERRORSELECT, "Error !",
- MB_OK | MB_ERROR, TRUE);
- return;
- }
- sOffset = (SHORT) WinSendDlgItemMsg(hwnd, IDD_WINLBOX,
- LM_QUERYSELECTION,0,0);
- if(sOffset<0) /* No item is currently selected */
- {
- MessageBox(hwnd, IDMSG_ERRORSELECT, "Error !",
- MB_OK | MB_ERROR, TRUE);
- return;
- }
- pFEA = GetCurFEA(hwnd,pHoldFEA); /* Gets a pointer to item to delete */
- if (pFEA == '\0')
- return;
- /* These two allocations should be checked for out of memory */
- GetMem((PPVOID)&pDL, sizeof(DELETELIST)); /* Add Name to Delete List */
- GetMem((PPVOID)&pDL->EAName, pFEA->cbName+1);
- strcpy(pDL->EAName,pFEA->szName);
- pDL->next = '\0';
-
- if(pDelList == '\0') /* The del list was previously empty */
- pDelList = pDL;
- else /* tack name onto the end of the list */
- {
- pDLcnt = pDelList;
- while(pDLcnt->next)
- pDLcnt = pDLcnt->next;
- pDLcnt->next = pDL;
- }
- WinSendDlgItemMsg(hwnd, IDD_WINLBOX,
- LM_DELETEITEM,MPFROMSHORT(sOffset),0L);
-
- if(sOffset<1) /* Remove pFEA from the linked list */
- {
- pHoldFEA = pFEA->next;
- }
- else
- {
- pFEAPrev = pHoldFEA;
-
- --sOffset;
- while(sOffset) /* Find previous EA */
- {
- pFEAPrev = pFEAPrev->next;
- --sOffset;
- }
- pFEAPrev->next = pFEA->next;
- }
- /* Check Type Name is in the list of MVST or not */
- for (i=0; i<MSNUM && MSdata[i].szName!=NULL &&
- strcmp(pFEA->szName,MSdata[i].szName)!=0;)
- i++;
-
- if(i<MSNUM && MSdata[i].szName!=NULL) /* Found the EA type in MVST list */
- {
- FreeMem(MSdata[i].szName);
- for (; i<MSNUM && MSdata[i+1].szName!=NULL; i++)
- {
- MSdata[i].szName = MSdata[i+1].szName;
- MSdata[i].usType = MSdata[i+1].usType;
- }
- }
- FreeMem(pFEA->szName); /* Release the memory */
- FreeMem(pFEA->aValue);
- FreeMem(pFEA);
-
- FILE_CHANGED = TRUE;
- return;
- }
-
- /****************************************************************\
- * *
- * Name: CurEAType(pFEA) *
- * *
- * Purpose: Given an EA structure, this routine returns the *
- * Type of the EA which resides in the first USHORT of*
- * the aValue member. This function is the same as *
- * GetUSHORT(pFEA,0). *
- * Usage : *
- * Method : Assumes a valid HoldFEA struct. *
- * *
- * Returns: The EA type. *
- * *
- \****************************************************************/
- ULONG CurEAType(HOLDFEA *pFEA) /* Same as GetUSHORT(,0); */
- {
- USHORT *pusType; /* EA Type is stored in first USHORT of aValue field */
-
- pusType = (USHORT *) pFEA->aValue;
- return(*pusType);
- }
-
- /****************************************************************\
- * *
- * Name: GetUSHORT(pFEA, index) *
- * *
- * Purpose: This routine returns the nth USHORT value in the *
- * aValue member of pFEA using index as the offset. *
- * Usage : *
- * Method : Assumes a valid HoldFEA struct and that index *
- * doesn't point outside the aValue buffer. *
- * *
- * Returns: The appropriate USHORT from the aValue field *
- * *
- \****************************************************************/
- USHORT GetUSHORT(HOLDFEA *pFEA, ULONG index)
- {
- USHORT *pusType;
-
- pusType = (USHORT *) pFEA->aValue;
- while(index-- > 0)
- pusType++;
- return(*pusType);
- }
-
- /****************************************************************\
- * *
- * Name: WriteEAs() *
- * *
- * Purpose: This routine updates the EAs on disk to reflect *
- * their current condition in memory. First, all EAs *
- * in the delete list are removed from the disk, then *
- * all EAs in the pHoldFEA list are written to disk. *
- * Usage : *
- * Method : This routine is not bulletproof as it does not get *
- * exclusive access to the file EAs, nor does it *
- * handle out of disk space sort of errors. Also, *
- * memory fetches are not fully error trapped. *
- * *
- * Returns: VOID. But cleans out the pDelList linked list. *
- * *
- \****************************************************************/
- VOID WriteEAs()
- {
- DELETELIST *pDL = pDelList,*pDLnext;
- HOLDFEA *pHFEA= pHoldFEA;
- EAOP2 eaopWrite;
- CHAR aBuf[MAX_GEA],*aPtr=NULL;
- FEA2 *pFEA = (FEA2 *) &aBuf[sizeof(ULONG)];
- USHORT usMemNeeded, usRet;
- ULONG *pulPtr=(ULONG *) aBuf; /* Initally points to top of FEALIST */
-
- if(!FILE_ISOPEN)
- {
- MessageBox(HWND_DESKTOP, IDMSG_NOFILEOPEN, "Error !",
- MB_OK | MB_ERROR, TRUE);
- return;
- }
- if (!FILE_CHANGED) /* Don't write unless it's necessary */
- return;
- eaopWrite.fpFEA2List = (FEA2LIST FAR *) aBuf; /* Setup fields that won't */
- pFEA->fEA = 0; /* change for the delete */
- pFEA->cbValue = 0; /* calls to DosSetPathInfo */
-
- while(pDL) /* Clean out all the deleted EA names */
- {
- pFEA->cbName = (UCHAR) strlen(pDL->EAName);
- *pulPtr = sizeof(FEA2LIST) + pFEA->cbName;
- strcpy(pFEA->szName,pDL->EAName);
- pFEA->oNextEntryOffset = 0L;
- /* Delete EA's by saying cbValue=0 */
- DosSetPathInfo(szFileName,
- SetInfoLevel2,
- (PVOID) &eaopWrite,
- sizeof(EAOP2),
- DSPI_WRTTHRU);
- pDLnext = pDL->next; /* Temp hold next pDL */
- FreeMem(pDL->EAName); /* Free up current Del struct */
- FreeMem(pDL);
- pDL = pDLnext; /* Set pDL to saved value */
- }
- pDelList = '\0'; /* DelList is now empty */
-
- while(pHFEA) /* Go through each HoldFEA */
- {
- usMemNeeded = sizeof(FEA2LIST) + pHFEA->cbName+1 +
- pHFEA->cbValue;
- GetMem((PPVOID)&aPtr, usMemNeeded);
-
- eaopWrite.fpFEA2List = (FEA2LIST FAR *) aPtr; /* Fill in eaop struct */
- eaopWrite.fpFEA2List->cbList = usMemNeeded;
-
- eaopWrite.fpFEA2List->list[0].fEA = pHFEA->fEA;
- eaopWrite.fpFEA2List->list[0].cbName = pHFEA->cbName;
- eaopWrite.fpFEA2List->list[0].cbValue = pHFEA->cbValue;
-
- strcpy(eaopWrite.fpFEA2List->list[0].szName, pHFEA->szName);
- memcpy(eaopWrite.fpFEA2List->list[0].szName + pHFEA->cbName+1,
- pHFEA->aValue, pHFEA->cbValue);
-
- usRet = DosSetPathInfo(szFileName, /* Write out the EA */
- FIL_QUERYEASIZE,
- (PVOID) &eaopWrite,
- sizeof(EAOP2),
- DSPI_WRTTHRU);
- if (usRet)
- {
- MessageBox(HWND_DESKTOP, IDMSG_WRITEERROR, "Error !",
- MB_OK | MB_ERROR, TRUE);
- FreeMem(aPtr); /* Free up the FEALIST struct */
- FILE_CHANGED = FALSE;
- return;
- }
- FreeMem(aPtr); /* Free up the FEALIST struct */
-
- pHFEA = pHFEA->next;
- }
- FILE_CHANGED = FALSE;
- MessageBox(HWND_DESKTOP, IDMSG_WRITEOK, "Note !", MB_OK, FALSE);
- return;
- }
-
- /****************************************************************\
- * *
- * Function name: EditEAValue(hwnd, pPDat) *
- * *
- * Purpose: This routine allows the entry/edit of an EA value *
- * condition in memory. First, all EAs in the delete *
- * list are removed from the disk, then all EAs in the*
- * pHoldFEA list are written out to disk. *
- * Usage : *
- * Method : Expects the PassData structure to tell it the *
- * HoldFEA to edit, and if it is a subfield of a multi*
- * -multi EA, the rest of the PassData structure will *
- * be filled into indicated which m-m is being edited.*
- * Note that if this is a new edit, usRetEAType is *
- * expected to be set to the proper EA type upon entry*
- * NOTE: memory sizing requests are not fully error trapped*
- * *
- * Returns: TRUE if the edit was successful. *
- * *
- \****************************************************************/
- BOOL EditEAValue(HWND hwnd, PPASSDATA pPDat)
- {
- USHORT usEAType; /* Holds the field type to be edited */
- USHORT *pusPtr;
- USHORT usSize; /* Holds the delta difference of the old and new buffers */
- CHAR *szNew=NULL,*szTrash; /* Temporary pointers */
- PASSDATA PDat;
- HOLDFEA *pFEA = (HOLDFEA *) pPDat->Point; /* The EA to be edited */
-
- /* Determine the type of EA that will be edited */
- if(pPDat->cbMulti) /* It's a multi-type job */
- {
- pusPtr = (USHORT *) MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset,
- pPDat->usIndex);
- usEAType = *pusPtr;
- }
- else if(pFEA->cbValue) /* It isn't a new EA name */
- {
- pusPtr = (USHORT *)pFEA->aValue;
- usEAType = *pusPtr;
- }
- else /* It's a new EA */
- usEAType = ConvTable[usRetEAType].usPrefix;
-
- PDat.Point = pFEA->szName; /* General setup for AsciiEditProc */
- /* =1 if there is a multi */
- PDat.usIndex =(USHORT)( pPDat->cbMulti ? 1 : 0);
- PDat.fFlag = (BYTE) ((pFEA->fEA & 0x80) ? TRUE : FALSE);
-
- switch(usEAType)
- {
- case EA_ASCIIZ:
- case EA_ASCIIZFN:
- case EA_ASCIIZEA:
- case EA_ASN1:
- if(pPDat->cbMulti) /* It is a multi-type field */
- szAscii=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset,
- pPDat->usIndex)
- +sizeof(USHORT);
- else if(pFEA->cbValue) /* There is a current value */
- szAscii=pFEA->aValue+sizeof(USHORT);
- else /* It's a new EA */
- szAscii='\0';
-
- if(!WinDlgBox(HWND_DESKTOP, /* Do an ascii text edit */
- hwnd,
- AsciiEditProc,
- '\0',
- IDD_ASCIIEDIT,
- &PDat))
- return(FALSE); /* They said cancel */
-
- if(PDat.fFlag) /* Handle the need/nice bit */
- PDat.fFlag = 0x80;
- if(PDat.fFlag != (BYTE)(PDat.fFlag & 0x80))
- FILE_CHANGED = TRUE;
- pFEA->fEA =(BYTE)( (pFEA->fEA & 0x7f) | PDat.fFlag );
-
- if(stricmp(strupr(szEAName),pFEA->szName)) /* The name changed */
- ChangeName(pFEA,szEAName);
-
- if(pFEA->cbValue) /* There is a current value */
- {
- if(!strcmp(szAscii,szScratch)) /* It hasn't changed */
- return(TRUE);
-
- if(pPDat->cbMulti) /* Do the whole thing here if m-m */
- { /* Change in size */
- usSize = (strlen(szScratch)-strlen(szAscii));
-
- if(usSize > 0) /* The new string is longer */
- {
- ResizeMem((PPVOID)&pFEA->aValue, /* Enlarge the EA size */
- pFEA->cbValue,
- pFEA->cbValue+usSize);
- szTrash=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset,
- (pPDat->usIndex+1));
- memmove(szTrash+usSize, /* Move end of EA to make room */
- szTrash,
- pFEA->cbValue-(szTrash-pFEA->aValue));
- }
- else
- {
- szTrash= MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset,
- (pPDat->usIndex+1));
- memmove(szTrash+usSize, /* Move back the end of the EA */
- szTrash,
- pFEA->cbValue-(szTrash-pFEA->aValue));
- DosSetMem(pFEA->aValue, pFEA->cbValue+usSize, fPERM|PAG_COMMIT);
- }
- szTrash=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset,
- pPDat->usIndex);
- strcpy(szTrash+sizeof(USHORT),szScratch); /* Copy in new val */
- pFEA->cbValue+=usSize; /* Change buffer count */
-
- FILE_CHANGED = TRUE;
- return(FILE_CHANGED); /* Done with m-m edit */
- }
- else
- {
- FreeMem(pFEA->aValue); /* Release old Value mem */
- }
- }
- GetMem((PPVOID)&szNew, strlen(szScratch)+3); /* +3 for Type & NULL */
- pusPtr = (USHORT *) szNew;
- *pusPtr= usEAType; /* Set type in new buffer */
- strcpy(szNew+2,szScratch); /* Copy in the new value */
- pFEA->aValue = szNew; /* Fix up the structure */
- pFEA->cbValue= (USHORT)(strlen(szScratch)+3);
-
- FILE_CHANGED = TRUE;
- return(FILE_CHANGED);
-
- case EA_LPBITMAP:
- case EA_LPICON:
- case EA_LPBINARY:
- case EA_LPASCII:
- case EA_LPMETAFILE:
- if (usEAType==EA_LPBITMAP || usEAType==EA_LPICON)
- {
- WinDlgBox(HWND_DESKTOP,
- hwnd,
- IconDlgProc,
- '\0',
- IDD_ABOUTBOX,
- NULL);
- }
- if(pPDat->cbMulti) /* It is a multi-type field */
- { /* szTrash points to field to edit, pusPtr to the field length */
- szTrash=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset,
- pPDat->usIndex);
- pusPtr = (USHORT *) ((CHAR *) szTrash + sizeof(USHORT));
- usSize = *pusPtr;
- if(usSize) /* It isn't a new EA */
- { /* Set up inital value for edit */
- GetMem((PPVOID)&szAscii, usSize+1);
- memcpy(szAscii,szTrash+2*sizeof(USHORT),usSize);
- *( ( CHAR *)szAscii + usSize ) ='\0';
- }
- else /* No inital value */
- szAscii = '\0';
- }
- else if(pFEA->cbValue) /* Single type && there is current value */
- {
- usSize=GetUSHORT(pFEA,1); /* Get size and set inital value */
- if(usSize)
- {
- GetMem((PPVOID)&szTrash, usSize+1); /* +1 for null */
- memcpy(szTrash,pFEA->aValue+4,usSize);
- szTrash[usSize]='\0';
- szAscii=szTrash;
- }
- else
- szAscii = '\0';
- }
- else
- szAscii = '\0';
-
- if(!WinDlgBox(HWND_DESKTOP, /* Do an ascii text edit */
- hwnd,
- AsciiEditProc,
- '\0',
- IDD_ASCIIEDIT,
- &PDat))
- { /* Cancel, but check if memory needs to be freed before exit */
- if(pPDat->cbMulti || pFEA->cbValue)
- if(szAscii) /* It's not NULL */
- FreeMem(szAscii); /* +1 for NULL */
- return(FALSE);
- }
- if(PDat.fFlag) /* Handle the need/nice bit */
- PDat.fFlag = 0x80;
- if(PDat.fFlag != (BYTE)(PDat.fFlag & 0x80))
- FILE_CHANGED = TRUE;
- pFEA->fEA = (BYTE)((pFEA->fEA & 0x7f) | PDat.fFlag);
-
- if(stricmp(strupr(szEAName),pFEA->szName)) /* The name changed */
- ChangeName(pFEA,szEAName);
-
- if(pFEA->cbValue) /* There is a current value */
- {
- if(szAscii && !strcmp(szAscii,szScratch)) /* It hasn't changed */
- {
- if(szAscii)
- FreeMem(szAscii);
- return(TRUE);
- }
- if(szAscii) /* Free default value buffer */
- FreeMem(szAscii);
-
- if(pPDat->cbMulti) /* Do the whole thing here is multi-type */
- { /* Change in len */
- USHORT usDelta = (USHORT)(strlen(szScratch) - usSize);
- if(usDelta > 0) /* The new string is longer, resize first */
- {
- ResizeMem((PPVOID)&pFEA->aValue, pFEA->cbValue, pFEA->cbValue+usDelta);
- szTrash= MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset,
- (pPDat->usIndex+1));
- memmove(szTrash+usDelta,szTrash,
- pFEA->cbValue-(szTrash-pFEA->aValue));
- }
- else
- {
- szTrash= MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset,
- (pPDat->usIndex+1));
- memmove(szTrash+usDelta,szTrash,
- pFEA->cbValue-(szTrash-pFEA->aValue));
- ResizeMem((PPVOID)&pFEA->aValue, pFEA->cbValue+usDelta, fPERM|PAG_COMMIT);
- }
- szTrash=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset,
- pPDat->usIndex);
- memmove(szTrash+2*sizeof(USHORT),szScratch,strlen(szScratch));
- pusPtr = (USHORT *) ((CHAR *)szTrash + sizeof(USHORT));
- *pusPtr= strlen(szScratch); /* Set the length field */
-
- pFEA->cbValue += usDelta; /* Adjust struct len field */
-
- FILE_CHANGED = TRUE;
- return(FILE_CHANGED);
- }
- FreeMem(pFEA->aValue); /* Free up old value */
- }
- GetMem((PPVOID)&szNew, strlen(szScratch)+4); /* Get space for new value */
- pusPtr = (USHORT *) szNew;
- *pusPtr= usEAType; /* Set type field */
- pusPtr++;
- *pusPtr= strlen(szScratch); /* Set length field */
- memcpy(szNew+4,szScratch,*pusPtr); /* Copy in new value */
- pFEA->aValue = szNew; /* Adjust pointers */
- pFEA->cbValue= strlen(szScratch)+4;/* +4 for type and LP cnt */
-
- FILE_CHANGED = TRUE;
- return(FILE_CHANGED);
-
- case EA_MVST:
- case EA_MVMT: /* It's multi-value multi-type */
- if(pFEA->cbValue == 0) /* It's a new EA */
- { /* Allocate empty m-m EA */
- GetMem((PPVOID)&pFEA->aValue, 3*sizeof(USHORT));
- pFEA->cbValue = 3*sizeof(USHORT);
- pusPtr = (USHORT *) pFEA->aValue;
- if(usEAType == EA_MVMT)
- *pusPtr = 0xffdf; /* Multi-value, multi-type */
- else
- *pusPtr = 0xffde; /* Multi-value, single-type */
- pusPtr+=2; /* Skip type, codepage */
- *pusPtr = 0; /* No fields initially */
- FILE_CHANGED = TRUE;
- }
- /* Set up passed in data */
- if(pPDat->cbMulti) /* It's a multi-type job */
- {
- szNew = MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset,
- pPDat->usIndex);
- szTrash = MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset,
- (pPDat->usIndex+1));
- PDat.usMultiOffset = (USHORT)(szNew - pFEA->aValue);
- PDat.cbMulti = (USHORT)(szTrash - szNew);
- }
- else
- {
- PDat.usMultiOffset = 0;
- PDat.cbMulti = pFEA->cbValue;
- }
- PDat.Point = (CHAR *) pFEA;
-
- WinDlgBox(HWND_DESKTOP, /* Do the Multi-type edit */
- hwnd,
- MultiTypeProc,
- '\0',
- IDD_MULTIBOX,
- &PDat);
- return(TRUE);
-
- default:
- return(FALSE);
- }
- return(FALSE);
- }
-
- /****************************************************************\
- * *
- * Name: EAExists(szEAName) *
- * *
- * Purpose: This routine goes through the linked list pointed *
- * to by global pHoldFEA and determines whether or not*
- * an EA othe passed name already exists. *
- * Usage: *
- * Method : The comparison is NOT case sensitive. *
- * *
- * Returns: TRUE if an EA with a name matching szEAName exists.*
- * *
- \****************************************************************/
- BOOL EAExists(CHAR *szEAName)
- {
- HOLDFEA *phFEA=pHoldFEA;
-
- while(phFEA)
- {
- if(!stricmp(szEAName,phFEA->szName))
- return(TRUE);
- phFEA=phFEA->next;
- }
- return(FALSE);
- }
-
- /****************************************************************\
- * *
- * Name: ChangeName(pFEA, szName) *
- * *
- * Purpose: This routine copies the current EA Name to the *
- * delete list, then allocates a new space, copies the*
- * new name into it, and sets the FEA pointer to it. *
- * Usage : *
- * Method : Not all the memory allocations are fully error *
- * trapped. *
- * *
- * Returns: VOID. Fixes up the pFEA structure and global *
- * pDelList. *
- * *
- \****************************************************************/
- VOID ChangeName(HOLDFEA *pFEA, CHAR *szName)
- {
- CHAR *szTemp=NULL;
- DELETELIST *pDL=NULL;
-
- GetMem((PPVOID)&szTemp, strlen(szName+1));/* Allocate space for new name */
- if(!szTemp)
- return;
- /* Allocate a new delete struct */
- GetMem((PPVOID)&pDL, sizeof(DELETELIST));
- pDL->EAName = pFEA->szName; /* Fill in DeleteList struct */
- pDL->next = pDelList;
- pDelList = pDL;
-
- strcpy(szTemp,szName); /* Copy name to permanent buffer */
- pFEA->szName = szTemp; /* Fix up struct */
- pFEA->cbName = (CHAR) strlen(szName);
-
- FILE_CHANGED = TRUE;
- return;
- }
-
- /****************************************************************\
- * *
- * Name: MultiTypeIndex(pMulti, usIndex) *
- * *
- * Purpose: This routine takes a pointer to a Multi-Multi data *
- * field and returns a pointer to the nth data field *
- * in this buffer. *
- * Usage: *
- * Method: Memory bounds are not checked and a corrupt EA field
- * could cause unspecified results. Recursively calls *
- * itself to handle nesting. Does not support multi- *
- * value single type fields. *
- * *
- * Returns: a pointer to the field specified by the usIndex *
- * parameters. *
- * *
- * Calls: LookupEAType, MultiTypeIndex() *
- * *
- \****************************************************************/
- CHAR *MultiTypeIndex(CHAR *pMulti, ULONG usIndex)
- {
- USHORT *pusPtr;
- USHORT usOffset;
- /* skip over 0xffdf, codepage, and field cnt */
- pMulti += 3*sizeof(USHORT);
-
- while(usIndex--) /* loop to skip over correct # of flds */
- {
- pusPtr = (USHORT *) pMulti; /* The address of EA data type stored */
- usOffset = LookupEAType(*pusPtr); /* Get offset of field type */
-
- pMulti += sizeof(USHORT); /* Skip over the type field to first data */
-
- switch(ConvTable[usOffset].usFldType)
- {
- case IDD_ASCIIZ:
- while(*pMulti) /* Increment to point after NULL */
- pMulti++;
- pMulti++;
- break;
-
- case IDD_LPDATA:
- pusPtr = (USHORT *) pMulti; /* Get the length of a data */
- pMulti += *pusPtr + sizeof(USHORT); /* skip to end */
- break;
-
- case IDD_MULTILIST:
- if(*pusPtr == EA_MVMT) /* m-m, do a recursive call to skip fld */
- {
- pusPtr = (USHORT *) pMulti; /* points to field cnt */
- pMulti = MultiTypeIndex(pMulti-sizeof(USHORT),*pusPtr);
- break;
- }
- /* implemented for Multi-valued single-type stuff... */
- pusPtr = (USHORT *) pMulti; /* Get the length of a data */
- pMulti += *pusPtr + sizeof(USHORT); /* skip to end */
- break;
- }
- }
- return(pMulti);
- }
-
- /****************************************************************\
- * *
- * Name: EAValueString(aEAVal) *
- * *
- * Purpose: This routine takes a pointer to an EA Value (i.e. *
- * starting with $ffxx) and returns a pointer to a *
- * string representing the value of the EA. This string
- * must be Freed by the user when finished with it. * *
- * Usage: *
- * Method : Not all GetMem's are totally error trapped. The *
- * string returned is allocated in this procedure, but*
- * it is the caller's responsibility to free the buffer
- * *
- * Returns: a pointer to an ASCII description of the field value
- * *
- \****************************************************************/
- CHAR *EAValueString(CHAR *aEAVal)
- {
- USHORT *pusPtr= (USHORT *) aEAVal; /* Points to EA Type */
- CHAR *szRet=NULL, *szTemp; /* szRet points to return string */
-
- switch(*pusPtr)
- {
- case EA_ASCIIZ: /* For asciiz strings, return MAXSHOWSIZE-1 chars */
- case EA_ASCIIZFN:
- case EA_ASCIIZEA:
- case EA_ASN1:
- aEAVal += sizeof(USHORT);
- if(strlen(aEAVal)<MAXSHOWSIZE)
- {
- GetMem((PPVOID)&szRet, strlen(aEAVal)+1);
- strcpy(szRet,aEAVal);
- }
- else
- {
- GetMem((PPVOID)&szRet, MAXSHOWSIZE);
- strncpy(szRet,aEAVal,MAXSHOWSIZE-4);
- strcpy (szRet+MAXSHOWSIZE-4,"...");
- szRet[MAXSHOWSIZE-1]='\0';
- }
- return(szRet);
-
- case EA_LPASCII: /* Display up to first MAXSHOWSIZE-1 chars */
- case EA_LPMETAFILE:
- pusPtr++;
- aEAVal += 2*sizeof(USHORT);
- if(*pusPtr < MAXSHOWSIZE)
- {
- GetMem((PPVOID)&szRet, *pusPtr +1);
- strncpy(szRet,aEAVal,*pusPtr);
- szRet[*pusPtr]='\0';
- }
- else
- {
- GetMem((PPVOID)&szRet, MAXSHOWSIZE);
- strncpy(szRet,aEAVal,MAXSHOWSIZE-4);
- strcpy (szRet+MAXSHOWSIZE-4,"...");
- szRet[MAXSHOWSIZE-1]='\0';
- }
- return(szRet);
- /* For the rest of the types, just display the field type */
- case EA_LPBINARY:
- szTemp = "*** LP Binary ***";
- break;
-
- case EA_LPBITMAP:
- szTemp = "*** LP Bitmap ***";
- break;
-
- case EA_LPICON:
- szTemp = "*** LP Icon ***";
- break;
-
- case EA_MVMT:
- szTemp = "*** Multi-value Multi-type ***";
- break;
-
- case EA_MVST:
- szTemp = "*** Multi-value Single-type ***";
- break;
-
- default:
- szTemp = "*** Unknown EA type ***";
- break;
-
- }
- GetMem((PPVOID)&szRet, strlen(szTemp)+1); /* Copy string from static to dynamic */
- strcpy(szRet,szTemp);
- return(szRet);
- }
-
- /****************************************************************\
- * *
- * Function name: MultiAdd(hwnd, pFEA, pPDat) *
- * *
- * Purpose: This routine is called by MultiTypeProc and handles*
- * the addition of a subvalue to a multi-value, multi-*
- * type EA. *
- * Usage : *
- * Method : Not all GetMem's are totally error trapped. It is *
- * possible that the add to the listbox could fail. *
- * *
- * Returns: VOID. Modifies the current pFEA. *
- * *
- \****************************************************************/
- VOID MultiAdd(HWND hwnd, HOLDFEA *pFEA, PPASSDATA pPDat)
- {
- USHORT usSize, i;
- USHORT *pusPtr;
- CHAR aUtility[6]; /* Used to hold the header for all EA types */
- CHAR *pInsert,*pValue;
- PASSDATA PDat;
-
- PDat.Point = pFEA->szName;
- /* Check Type Name is in the list of MVST or not */
- for (i=0; i<MSNUM && MSdata[i].szName!=NULL &&
- strcmp(PDat.Point,MSdata[i].szName)!=0;)
- i++;
-
- if(ConvTable[usRetEAType].usPrefix != EA_MVST && i==MSNUM)
- {
- if(!WinDlgBox(HWND_DESKTOP, /* Get the name and type */
- hwnd,
- AddEAProc,
- '\0',
- IDD_ADDEA,
- &PDat))
- return; /* They said cancel */
- }
- else /* MVST */
- {
- if (i < MSNUM && MSdata[i].szName!=NULL && MSdata[i].usType<10)
- usRetEAType = MSdata[i].usType; /* EAname & type exist */
- else
- if(!WinDlgBox(HWND_DESKTOP, /* EAname is new, get the new type */
- hwnd,
- AddEAProc,
- '\0',
- IDD_ADDEA,
- &PDat))
- return; /* They said cancel */
- }
- pusPtr = (USHORT *) aUtility;
- *pusPtr= ConvTable[usRetEAType].usPrefix; /* Set the type in header buf */
-
- switch(ConvTable[usRetEAType].usFldType)
- {
- case IDD_ASCIIZ: /* make buffer look like: xx FF 00, size 3 */
- usSize = 3;
- aUtility[2]=0;
- break;
-
- case IDD_LPDATA: /* make the buffer look like: xx FF 00 00, size 4 */
- usSize = 4;
- pusPtr = (USHORT *) &aUtility[2];
- *pusPtr= 0;
- break;
-
- case IDD_MULTILIST:
- usSize = 6;
- pusPtr = (USHORT *) &aUtility[2];
- *pusPtr= 0; /* Zero out codepage */
- pusPtr++;
- *pusPtr= 0; /* Zero out fld cnt */
- break;
- }
- /* Increase EA size to accomodate the header */
- ResizeMem((PPVOID)&pFEA->aValue, pFEA->cbValue, pFEA->cbValue+usSize);
-
- pusPtr = (USHORT *) ((CHAR *) pFEA->aValue + pPDat->usMultiOffset);
- pusPtr+=2; /* Point to the current number of m-m fields */
-
- /* Get ptr to beginning of current EA, scoot the rest down and insert
- the 3-4 byte header at the end of the list. */
- pInsert = MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset, *pusPtr);
- memmove(pInsert+usSize,pInsert, pFEA->cbValue-(pInsert-pFEA->aValue));
- memcpy(pInsert,aUtility,usSize);
-
- pFEA->cbValue += usSize; /* Fix up the counts */
- pPDat->cbMulti+= usSize;
- /* Set the PDat for call */
- PDat.Point = (CHAR *) pFEA;
- PDat.cbMulti = pPDat->cbMulti;
- PDat.usMultiOffset = pPDat->usMultiOffset;
- PDat.usIndex = *pusPtr;
-
- if(!EditEAValue(hwnd,&PDat)) /* They canceled the edit */
- { /* Move the EA's back to effectively kill the inserted header */
- memmove(pInsert,pInsert+usSize,pFEA->cbValue-(pInsert-pFEA->aValue));
- DosSetMem(pFEA->aValue, pFEA->cbValue-usSize, fPERM|PAG_COMMIT);
- pFEA->cbValue -= usSize; /* Adjust counters */
- pPDat->cbMulti-= usSize;
-
- return;
- }
- /* Reset pusPtr since EditEAValue could have moved the base address */
- pusPtr = (USHORT *) ((CHAR *) pFEA->aValue + pPDat->usMultiOffset);
- pusPtr+=2;
-
- pInsert = MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset, *pusPtr);
-
- *pusPtr += 1; /* Field cnt incremented AFTER call to Edit */
-
- pValue = EAValueString(pInsert); /* Add new field to the list box */
-
- WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_INSERTITEM,
- MPFROM2SHORT(LIT_END,0),
- MPFROMP(pValue));
- FreeMem(pValue);
-
- FILE_CHANGED = TRUE;
- return;
- }
-