home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************
-
- This module contains subroutines for nead.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
- EditEAValues() Handles editing a given EA (also 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 an EA
- MultiAdd() Handles addition of a field for m-m
-
- **************************************************************/
-
- #include "nead.h"
-
- /************ External GLOBALS *******************************/
-
- extern CHAR szFileName[CCHMAXPATH];
- extern CHAR szEAName[MAXEANAME+1];
- extern USHORT usRetEAType;
- extern BOOL FILE_ISOPEN;
- extern BOOL FILE_CHANGED;
- extern BOOL COMMAND_LINE_FILE;
- extern HHEAP hhp;
- extern CHAR *pAlloc,*szEditBuf,*szAscii,*szScratch;
- extern HOLDFEA *pHoldFEA;
- extern DELETELIST *pDelList;
- extern EADATA ConvTable[EATABLESIZE];
-
- /*************************************************************/
-
-
- /*
- * Function name: AddEA()
- *
- * Parameters: hwnd which is the current window handle.
- *
- * Returns: TRUE iff the EA is successfully added.
- *
- * Purpose: This routine handles the addition of a new EA to the linked list.
- *
- * Usage/Warnings: Routine does NOT do full memory error trapping and the
- * insert message to the l-box is not error checked.
- *
- * Calls: EditEAValue()
- */
-
- BOOL AddEA(HWND hwnd)
- {
- HOLDFEA *pFEA=pHoldFEA; /* Points to the beginning of the EA list */
- HOLDFEA *pNewFEA; /* Used to temporarily hold the new EA */
- PASSDATA PData;
-
- if(!FILE_ISOPEN)
- return(FALSE);
-
- if(!WinDlgBox(HWND_DESKTOP, /* get new EA name and type */
- hwnd,
- AddEAProc,
- (HMODULE)NULL,
- IDD_ADDEA,
- NULL))
- return(FALSE); /* they said cancel */
-
- GetMem(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 */
-
- GetMem(pNewFEA->szName,pNewFEA->cbName+1); /* Name returned in szEAName */
- strcpy(pNewFEA->szName,strupr(szEAName));
- pNewFEA->aValue = NULL;
- pNewFEA->next = NULL;
-
- if(pHoldFEA == NULL) /* 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 = NULL; /* Disconnect the partial new EA */
- else
- pHoldFEA = NULL; /* The new EA was the first one */
-
- FreeMem(pNewFEA->szName,pNewFEA->cbName+1);
- FreeMem(pNewFEA,sizeof(HOLDFEA));
-
- return(FALSE);
- }
-
- WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_INSERTITEM, /* Insert name in L-Box */
- MPFROM2SHORT(LIT_END,0),
- MPFROMP(pNewFEA->szName));
-
- return(TRUE);
- }
-
-
- /*
- * Function name: QueryEAs()
- *
- * Parameters: hwnd which is the current window handle.
- * pszPath points to the path of the file to grab EAs from.
- *
- * Returns: TRUE iff it successfully reads in the EAs. Upon exit, global
- * pHoldFEA points to a linked list of the EAs for the current file.
- *
- * Purpose: Call DOS to Query a file's EA names and values.
- *
- * Usage/Warnings: 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.
- *
- * Calls: Free_FEAList(), CheckEAIntegrity()
- */
-
- BOOL QueryEAs(HWND hwnd,CHAR *pszPath)
- {
- CHAR *pAlloc; /* Holds the FEA struct returned by DosEnumAttribute */
- /* also used to create the GEALIST for DosQPathInfo */
- CHAR *pBigAlloc; /* Temp buffer to hold each EA as it is read in */
- USHORT cbBigAlloc; /* 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; /* Points to last EA added, so new EA can link */
- HOLDFEA *pNewFEA; /* Struct to build the new EA in */
-
- FEA *pFEA; /* Used to read from Enum's return buffer */
- GEALIST *pGEAList; /* Ptr used to set up buffer for DosQPathInfo call */
- EAOP eaopGet; /* Used to call DosQPathInfo */
-
- GetMem((HHEAP) pAlloc,(USHORT) MAX_GEA); /* Allocate enough room for any GEA List */
- pFEA = (FEA *) pAlloc; /* pFEA always uses pAlloc buffer */
-
- pHoldFEA = NULL; /* 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, */
- pAlloc, /* so DosQPathInfo must be */
- MAX_GEA, /* called to get it. */
- &ulEnumCnt,
- (LONG) GetInfoLevel1,
- 0L))
- break; /* There was some sort of error */
-
- if(ulEnumCnt != 1) /* All the EAs have been read */
- break;
-
- ulEntryNum++;
-
- GetMem(pNewFEA,sizeof(HOLDFEA));
-
- if (pNewFEA == NULL) /* Out of memory */
- {
- FreeMem(pAlloc,MAX_GEA);
- 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 = NULL;
-
- GetMem(pNewFEA->szName,pFEA->cbName +1); /* Allocate for 2 arrays */
- GetMem(pNewFEA->aValue,pFEA->cbValue);
-
- if (!pNewFEA->szName || !pNewFEA->aValue) /* Out of memory */
- {
- if(pNewFEA->szName)
- FreeMem(pNewFEA->szName,pFEA->cbName+1);
- if(pNewFEA->aValue)
- FreeMem(pNewFEA->aValue,pFEA->cbValue);
-
- FreeMem(pAlloc, MAX_GEA);
- FreeMem(pNewFEA,sizeof(HOLDFEA));
-
- Free_FEAList(pHoldFEA,pDelList);
- return (FALSE);
- }
- strcpy(pNewFEA->szName,pAlloc+sizeof(FEA)); /* Copy in EA Name */
-
- cbBigAlloc = sizeof(FEALIST) + pNewFEA->cbName+1 + pNewFEA->cbValue;
- GetMem(pBigAlloc,cbBigAlloc);
- if (pBigAlloc == NULL)
- {
- FreeMem(pNewFEA->szName,pFEA->cbName+1);
- FreeMem(pNewFEA->aValue,pFEA->cbValue);
- FreeMem(pAlloc, MAX_GEA);
- FreeMem(pNewFEA,sizeof(HOLDFEA));
- Free_FEAList(pHoldFEA,pDelList);
- return (FALSE);
- }
-
- pGEAList = (GEALIST *) pAlloc; /* Set up GEAList structure */
-
- pGEAList->cbList = sizeof(GEALIST) + pNewFEA->cbName; /* +1 for NULL */
- pGEAList->list[0].cbName = pNewFEA->cbName;
- strcpy(pGEAList->list[0].szName,pNewFEA->szName);
-
- eaopGet.fpGEAList = (GEALIST far *) pAlloc;
- eaopGet.fpFEAList = (FEALIST far *) pBigAlloc;
-
- eaopGet.fpFEAList->cbList = cbBigAlloc;
-
- DosQPathInfo(pszPath, /* Get the complete EA info */
- GetInfoLevel3,
- (PVOID) &eaopGet,
- sizeof(EAOP),
- 0L);
- memcpy(pNewFEA->aValue, /* Copy the value to HoldFEA */
- pBigAlloc+sizeof(FEALIST)+pNewFEA->cbName+1,
- pNewFEA->cbValue);
-
- FreeMem(pBigAlloc,cbBigAlloc); /* Release the temp Enum buffer */
-
- if(!CheckEAIntegrity(pNewFEA->aValue,pNewFEA->cbValue)) /* Bad EA */
- {
- FreeMem(pNewFEA->szName,pFEA->cbName+1);
- FreeMem(pNewFEA->aValue,pFEA->cbValue);
- FreeMem(pNewFEA,sizeof(HOLDFEA));
- continue; /* Don't add this EA to linked list */
- }
-
- if(pHoldFEA == NULL) /* 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(pAlloc, MAX_GEA); /* Free up the GEA buf for DosEnum */
- return (TRUE);
- }
-
-
- /*
- * Function name: CheckEAIntegrity()
- *
- * Parameters: aBuf points to the buffer to check for a valid EA.
- * cbBuf is the allocated length of aBuf.
- *
- * Returns: TRUE iff 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/Warnings: 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.
- *
- * Calls: MultiTypeIndex()
- */
-
- BOOL CheckEAIntegrity(CHAR *aBuf,USHORT 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 == (SHORT) cbBuf)
- return TRUE;
- else
- return FALSE;
- }
- else /* Single type, multi-value is not yet implemented */
- {
- return TRUE;
- }
- default:
- return FALSE;
- }
- return TRUE;
- }
-
-
- /*
- * Function name: Free_FEAList()
- *
- * Parameters: pFEA points to the beginning of the linked list to be freed.
- * pDList points to the beginning of the deleted linked list.
- *
- * Returns: VOID. The two linked lists passed in are cleaned out though.
- *
- * 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/Warnings: Note that NEAD 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.
- *
- * Calls:
- */
-
- 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,pFEA->cbName+1);
- if(pFEA->aValue) /* Free if non-NULL value */
- FreeMem(pFEA->aValue,pFEA->cbValue);
-
- FreeMem(pFEA,sizeof(HOLDFEA)); /* Free HoldFEA struct */
- pFEA = next;
- }
-
- while(pDList)
- {
- Dnext = pDList->next;
- if(pDList->EAName)
- FreeMem(pDList->EAName,strlen(pDList->EAName)+1);
- FreeMem(pDList,sizeof(DELETELIST));
- pDList = Dnext;
- }
- }
-
-
- /*
- * Function name: LookupEAType()
- *
- * Parameters: usType is tye EA type to be looked up.
- *
- * 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.
- *
- * Purpose: This routine takes EA type and returns an offset into ConvTable
- * which points to an entry that describes the type passed in.
- *
- * Usage/Warnings:
- *
- * Calls:
- */
-
- USHORT LookupEAType(USHORT usType)
- {
- USHORT cnt;
-
- for(cnt=0;cnt<EATABLESIZE-1;cnt++)
- if(ConvTable[cnt].usPrefix == usType)
- return(cnt);
- return(cnt);
- }
-
-
- /*
- * Function name: DeleteCurEA()
- *
- * Parameters: hwnd is the current window handle.
- *
- * Returns: VOID. Removes one item from global pHoldFEA list and adds one
- * to global pDelList.
- *
- * 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/Warnings: The memory allocation routines are NOT fully error trapped.
- *
- * Calls: GetCurFEA()
- */
-
- VOID DeleteCurEA(HWND hwnd)
- {
- HOLDFEA *pFEA,*pFEAPrev;
- DELETELIST *pDL,*pDLcnt; /* Utility ptrs for manipulating the Del list */
- LONG lOffset;
-
- pFEA = GetCurFEA(hwnd,pHoldFEA); /* Gets a pointer to item to delete */
- if (pFEA == NULL)
- return;
-
- /* These two allocations should be checked for out of memory */
- GetMem(pDL,sizeof(DELETELIST)); /* Add Name to Delete List */
- GetMem(pDL->EAName,pFEA->cbName+1);
- strcpy(pDL->EAName,pFEA->szName);
- pDL->next = NULL;
-
- if(pDelList == NULL) /* 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;
- }
-
- lOffset = (LONG) WinSendDlgItemMsg(hwnd, IDD_LBOX,
- LM_QUERYSELECTION,0,0);
- WinSendDlgItemMsg(hwnd, IDD_LBOX,
- LM_DELETEITEM,MPFROMSHORT((SHORT) lOffset),0L);
-
- if(lOffset<1) /* Remove pFEA from the linked list */
- {
- pHoldFEA = pFEA->next;
- }
- else
- {
- pFEAPrev = pHoldFEA;
-
- while(--lOffset) /* Find previous EA */
- pFEAPrev = pFEAPrev->next;
-
- pFEAPrev->next = pFEA->next;
- }
-
- FreeMem(pFEA->szName,pFEA->cbName+1); /* Release the memory */
- FreeMem(pFEA->aValue,pFEA->cbValue);
- FreeMem(pFEA,sizeof(HOLDFEA));
-
- FILE_CHANGED = TRUE;
- }
-
-
- /*
- * Function name: CurEAType()
- *
- * Parameters: pFEA points to the FEA struct to use.
- *
- * Returns: The EA type.
- *
- * 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/Warnings: Assumes a valid HoldFEA struct.
- *
- * Calls:
- */
-
- USHORT 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);
- }
-
-
- /*
- * Function name: GetUSHORT()
- *
- * Parameters: pFEA points to the FEA struct to use.
- * index is an offset of the USHORT to be returned
- *
- * Returns: The appropriate USHORT from the aValue field
- *
- * Purpose: This routine returns the nth USHORT value in the aValue member
- * of pFEA using index as the offset.
- *
- * Usage/Warnings: Assumes a valid HoldFEA struct and that index doesn't
- * point outside the aValue buffer.
- *
- * Calls:
- */
-
- USHORT GetUSHORT(HOLDFEA *pFEA,USHORT index)
- {
- USHORT *pusType;
-
- pusType = (USHORT *) pFEA->aValue;
- while(index-- > 0)
- pusType++;
- return(*pusType);
- }
-
-
- /*
- * Function name: WriteEAs()
- *
- * Parameters: hwnd is the current window handle used only by memory
- * allocation error handling.
- *
- * Returns: VOID. But cleans out the pDelList linked list.
- *
- * 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 out to disk.
- *
- * Usage/Warnings: NOTE: 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.
- *
- * Calls:
- */
-
- VOID WriteEAs(HWND hwnd)
- {
- DELETELIST *pDL = pDelList,*pDLnext;
- HOLDFEA *pHFEA= pHoldFEA;
- EAOP eaopWrite;
- CHAR aBuf[MAX_GEA],*aPtr;
- FEA *pFEA = (FEA *) &aBuf[sizeof(ULONG)];
- USHORT usRet,usMemNeeded;
- ULONG *pulPtr=(ULONG *) aBuf; /* Initally points to top of FEALIST */
-
- if(!FILE_ISOPEN || !FILE_CHANGED) /* Don't write unless it's necessary */
- return;
-
- eaopWrite.fpFEAList = (FEALIST 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(FEALIST) + pFEA->cbName+1; /* +1 for NULL */
- strcpy(aBuf+sizeof(FEALIST),pDL->EAName);
-
- usRet=DosSetPathInfo(szFileName, /* Delete EA's by saying cbValue=0 */
- SetInfoLevel2,
- (PVOID) &eaopWrite,
- (USHORT) sizeof(EAOP),
- DSPI_WRTTHRU,
- 0L);
-
- pDLnext = pDL->next; /* Temp hold next pDL */
- FreeMem(pDL->EAName, pFEA->cbName+1); /* Free up current Del struct */
- FreeMem(pDL, sizeof(DELETELIST));
- pDL = pDLnext; /* Set pDL to saved value */
- }
- pDelList = NULL; /* DelList is now empty */
-
- while(pHFEA) /* Go through each HoldFEA */
- {
- usMemNeeded = sizeof(FEALIST) + pHFEA->cbName+1 + pHFEA->cbValue;
- GetMem(aPtr,usMemNeeded);
-
- eaopWrite.fpFEAList = (FEALIST far *) aPtr; /* Fill in eaop struct */
- eaopWrite.fpFEAList->cbList = usMemNeeded;
-
- eaopWrite.fpFEAList->list[0].fEA = pHFEA->fEA;
- eaopWrite.fpFEAList->list[0].cbName = pHFEA->cbName;
- eaopWrite.fpFEAList->list[0].cbValue = pHFEA->cbValue;
-
- strcpy(aPtr + sizeof(FEALIST), pHFEA->szName);
- memcpy(aPtr + sizeof(FEALIST) + pHFEA->cbName+1,
- pHFEA->aValue, pHFEA->cbValue);
-
- usRet=DosSetPathInfo(szFileName, /* Write out the EA */
- SetInfoLevel2,
- (PVOID) &eaopWrite,
- (USHORT) sizeof(EAOP),
- DSPI_WRTTHRU,0L);
-
- FreeMem(aPtr,usMemNeeded); /* Free up the FEALIST struct */
-
- pHFEA = pHFEA->next;
- }
-
- FILE_CHANGED = FALSE;
- }
-
-
- /*
- * Function name: EditEAValue()
- *
- * Parameters: hwnd is the current window handle.
- * pPDat is a pointer to PassData which contains Edit EA info.
- *
- * Returns: TRUE iff the edit was successful.
- *
- * 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/Warnings: 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 in
- * to 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.
- *
- * Calls: MultiTypeIndex(), ChangeName(), AsciiEditProc() (thru PM),
- * MultiTypeProc() (thru PM).
- */
-
- BOOL EditEAValue(HWND hwnd, PASSDATA *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,*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 */
- PDat.usIndex = pPDat->cbMulti ? 1 : 0; /* =1 if there is a multi */
- 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=NULL;
-
-
- if(!WinDlgBox(HWND_DESKTOP, /* Do an ascii text edit */
- hwnd,
- AsciiEditProc,
- (HMODULE) NULL,
- 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(hwnd,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 */
- {
- usSize = strlen(szScratch)-strlen(szAscii); /* Change in size */
-
- if(usSize > 0) /* The new string is longer */
- {
- ResizeMem(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 /* The new string is shorter */
- {
- 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));
- ResizeMem(pFEA->aValue, /* Shrink the EA buffer */
- pFEA->cbValue,
- pFEA->cbValue+usSize);
- }
- szTrash=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset,
- pPDat->usIndex);
- strcpy(szTrash+sizeof(USHORT),szScratch); /* Copy in new val */
- pFEA->cbValue+=usSize; /* Change buffer count */
-
- return(FILE_CHANGED = TRUE); /* Done with m-m edit */
- }
- else
- {
- FreeMem(pFEA->aValue,pFEA->cbValue); /* Release old Value mem */
- }
- }
- GetMem(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= strlen(szScratch)+3;
-
- return(FILE_CHANGED = TRUE);
-
- case EA_LPBINARY:
- case EA_LPASCII:
- case EA_LPMETAFILE:
- 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 */
- {
- GetMem(szAscii,usSize+1); /* Set up inital value for edit */
- memcpy(szAscii,szTrash+2*sizeof(USHORT),usSize);
- szAscii[usSize]=0;
- }
- else /* No inital value */
- szAscii = NULL;
- }
- else if(pFEA->cbValue)
- {
- usSize=GetUSHORT(pFEA,1); /* Get size and set inital value */
- if(usSize)
- {
- GetMem(szTrash,usSize+1); /* +1 for null */
- memcpy(szTrash,pFEA->aValue+4,usSize);
- szTrash[usSize]=0;
- szAscii=szTrash;
- }
- else
- szAscii = NULL;
- }
- else
- szAscii = NULL;
-
- if(!WinDlgBox(HWND_DESKTOP, /* Do an ascii text edit */
- hwnd,
- AsciiEditProc,
- (HMODULE) NULL,
- 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,strlen(szAscii)+1); /* +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(hwnd,pFEA,szEAName);
-
- if(pFEA->cbValue) /* There is a current value */
- {
- if(!strcmp(szAscii,szScratch)) /* It hasn't changed */
- {
- if(szAscii)
- FreeMem(szAscii,usSize+1);
- return(TRUE);
- }
- if(szAscii) /* Free default value buffer */
- FreeMem(szAscii,usSize+1);
-
- if(pPDat->cbMulti) /* Do the whole thing here is multi-type */
- {
- USHORT usDelta = strlen(szScratch) - usSize; /* Change in len */
- if(usDelta > 0) /* The new string is longer, resize first */
- {
- ResizeMem(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 /* move first, resize afterwards */
- {
- szTrash=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset,
- pPDat->usIndex+1);
- memmove(szTrash+usDelta,szTrash,
- pFEA->cbValue-(szTrash-pFEA->aValue));
- ResizeMem(pFEA->aValue,pFEA->cbValue,pFEA->cbValue+usDelta);
- }
- 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 */
-
- return(FILE_CHANGED = TRUE);
- }
-
- FreeMem(pFEA->aValue,pFEA->cbValue); /* Free up old value */
- }
- GetMem(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 */
-
- return(FILE_CHANGED = TRUE);
-
- case EA_MVMT: /* It's multi-value multi-type */
- if(pFEA->cbValue == 0) /* It's a new EA */
- {
- GetMem(pFEA->aValue,3*sizeof(USHORT)); /* Allocate empty m-m EA */
- pFEA->cbValue = 3*sizeof(USHORT);
- pusPtr = (USHORT *) pFEA->aValue;
- *pusPtr = 0xffdf; /* Multi-value, multi-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 = szNew - pFEA->aValue;
- PDat.cbMulti = szTrash - szNew;
- }
- else
- {
- PDat.usMultiOffset = 0;
- PDat.cbMulti = pFEA->cbValue;
- }
- PDat.Point = (CHAR *) pFEA;
-
- WinDlgBox(HWND_DESKTOP, /* Do the Multi-type edit */
- hwnd,
- MultiTypeProc,
- (HMODULE) NULL,
- IDD_MULTIBOX,
- &PDat);
- return(TRUE);
-
- }
- }
-
-
- /*
- * Function name: EAExists()
- *
- * Parameters: szEAName points to the EA Name to check for.
- *
- * Returns: TRUE iff an EA with a name matching szEAName exists.
- *
- * Purpose: This routine goes through the linked list pointed to by global
- * pHoldFEA and determines whether or not an EA of the passed name
- * already exists.
- *
- * Usage/Warnings: The comparison is NOT case sensitive.
- *
- * Calls:
- *
- */
-
- BOOL EAExists(CHAR *szEAName)
- {
- HOLDFEA *phFEA=pHoldFEA;
-
- while(phFEA)
- {
- if(!stricmp(szEAName,phFEA->szName))
- return(TRUE);
- phFEA=phFEA->next;
- }
- return(FALSE);
- }
-
-
- /*
- * Function name: ChangeName()
- *
- * Parameters: hwnd is the current window used for error messages.
- * pFEA points to the current FEA.
- * szName points to the new EA name.
- *
- * Returns: VOID. Fixes up the pFEA structure and global pDelList.
- *
- * 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/Warnings: NOTE: Not all the memory allocations are fully error
- * trapped.
- *
- * Calls:
- *
- */
-
- VOID ChangeName(HWND hwnd,HOLDFEA *pFEA,CHAR *szName)
- {
- CHAR *szTemp;
- DELETELIST *pDL;
-
- GetMem(szTemp,strlen(szName+1)); /* Allocate space for new name */
- if(!szTemp)
- return;
-
- GetMem(pDL,(USHORT) sizeof(DELETELIST)); /* Allocate a new delete struct */
- 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;
- }
-
-
- /*
- * Function name: MultiTypeIndex()
- *
- * Parameters: pMulti points to the current m-m field.
- * usIndex is the field the caller is interested in.
- *
- * Returns: a pointer to the field specified by the usIndex param.
- *
- * 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/Warnings: NOTE: 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.
- *
- * Calls: LookupEAType, MultiTypeIndex()
- *
- */
-
- CHAR *MultiTypeIndex(CHAR *pMulti, USHORT usIndex)
- {
- USHORT *pusPtr;
- USHORT usOffset;
-
- pMulti += 3*sizeof(USHORT); /* skip over 0xffdf, codepage, and field cnt */
-
- while(usIndex--) /* loop to skip over correct # of flds */
- {
- pusPtr = (USHORT *) pMulti;
- usOffset = LookupEAType(*pusPtr); /* Get offset of field type */
-
- pMulti += sizeof(USHORT); /* Skip over the type field */
-
- switch(ConvTable[usOffset].usFldType)
- {
- case IDD_ASCIIZ:
- while(*pMulti++); /* Increment to point after NULL */
- break;
-
- case IDD_LPDATA:
- pusPtr = (USHORT *) pMulti; /* Get the length */
- 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;
- }
- /* Not yet implemented for Multi-valued single-type stuff... */
- break;
- }
- }
- return(pMulti);
- }
-
-
- /*
- * Function name: EAValueString()
- *
- * Parameters: hwnd is the current window handle.
- * aEAVal is a pointer to an EA value field.
- *
- * Returns: a pointer to an ASCII description of the field value.
- *
- * Purpose: This routine takes a pointer to an EA Value (i.e. starting with
- * 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/Warnings: NOTE: 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.
- *
- * Calls:
- *
- */
-
- CHAR *EAValueString(HWND hwnd,CHAR *aEAVal)
- {
- USHORT *pusPtr= (USHORT *) aEAVal; /* Points to EA Type */
- CHAR *szRet,*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(szRet,strlen(aEAVal)+1);
- strcpy(szRet,aEAVal);
- }
- else
- {
- GetMem(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(szRet,*pusPtr +1);
- strncpy(szRet,aEAVal,*pusPtr);
- szRet[*pusPtr]=0;
- }
- else
- {
- GetMem(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(szRet,strlen(szTemp)+1); /* Copy string from static to dynamic */
- strcpy(szRet,szTemp);
- return(szRet);
- }
-
-
- /*
- * Function name: MultiAdd()
- *
- * Parameters: hwnd is the current window handle.
- * pFEA points to the current FEA.
- * pPDat gives the current m-m data.
- *
- * Returns: VOID. Modifies the current pFEA.
- *
- * Purpose: This routine is called by MultiTypeProc and handles the addition
- * of a subvalue to a multi-value, multi-type EA.
- *
- * Usage/Warnings: NOTE: Not all GetMem's are totally error trapped.
- * It is also possible that the add to the listbox could fail.
- *
- * Calls: AddEAProc() (thru PM), MultiTypeIndex()
- *
- */
-
- VOID MultiAdd(HWND hwnd, HOLDFEA *pFEA,PASSDATA FAR *pPDat)
- {
- USHORT usSize;
- USHORT *pusPtr;
- CHAR aUtility[6]; /* Used to hold the header for all EA types */
- CHAR *pInsert,*pValue;
- PASSDATA PDat;
-
- PDat.Point = pFEA->szName;
-
- if(!WinDlgBox(HWND_DESKTOP, /* Get the name and type */
- hwnd,
- AddEAProc,
- (HMODULE) NULL,
- 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(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));
- ResizeMem(pFEA->aValue,pFEA->cbValue,pFEA->cbValue-usSize);
- 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(hwnd,pInsert); /* Add new field to the list box */
-
- WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_INSERTITEM,
- MPFROM2SHORT(LIT_END,0),
- MPFROMP(pValue));
- FreeMem(pValue,strlen(pValue)+1);
-
- FILE_CHANGED = TRUE;
- }
-
-