Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

320 lines
9.1 KiB

/*****************************************************************************
*
* HCTC.C
*
* Copyright (C) Microsoft Corporation 1990.
* All Rights reserved.
*
*****************************************************************************/
#include "help.h"
// #include "inc\wprintf.h"
_subsystem(WINAPP);
static GH STDCALL GhCopyLayoutText(QDE, HTE, GH, QL, QL, QW);
/*----------------------------------------------------------------------------+
| FCopyToClipboardHwnd(hwnd) |
| |
| Purpose: |
| Copy the text of the current topic to the Clipboard. |
| |
| Arguments: |
| hwnd Handle to the caller's help window. |
| |
| Returns: |
| TRUE if successful, FALSE otherwise. |
| |
| Method: |
| Allocates an initial chunk of memory of CLIPALLOCSIZE, then calls |
| WCopyLayoutText with this buffer, once for the NSR and once for |
| SR, then terminates the buffer with a NULL char. It then puts the |
| buffer to the clipboard. WCopyLayoutText will attempt to expand the |
| buffer if it needs more room. |
| |
| Notes: |
| We use direct Win 3.0 mem mgr calls to avoid extra debug bytes. |
| We allocate with GPTR, which zero-inits memory, and use non-discardable |
| memory. |
| |
| To avoid generating an error twice, we use the fWithholdError flag, |
| which is set to TRUE if we get an error from a function that we "know" |
| has taken care of generating an error. Yuck. |
+----------------------------------------------------------------------------*/
BOOL STDCALL FCopyToClipboardHwnd(HWND hwnd)
{
HWND hwndTemp;
HDE hdeCopy = NULL;
HGLOBAL gh;
LONG lcbTotal;
LONG lcbAlloc;
int cDE;
WORD wErr;
BOOL fWithholdError = FALSE;
QDE qdeCopy;
HGLOBAL hglbNew;
HWND hwndTopic = hwndNote ? hwndNote : ahwnd[iCurWindow].hwndTopic;
hwndTemp = HwndGetEnv();
lcbAlloc = CLIPALLOCSIZE;
lcbTotal = 0L;
if (!(gh = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, CLIPALLOCSIZE))) {
PostErrorMessage(wERRS_OOM);
return FALSE;
}
for (cDE = (hwndNote ? 1 : 0); cDE < 2; ++cDE) {
HTE hte;
HDC hdc;
HDE hdeCur;
// Select the non-scrolling region or the scrolling region in turn
if (cDE == 0 && !hwndNote) {
// The NSR DE
hdeCur = HdeGetEnvHwnd(ahwnd[iCurWindow].hwndTitle);
if (hdeCur && !FTopicHasNSR(hdeCur))
hdeCur = NULL;
}
else {
// The SR DE
hdeCur = HdeGetEnvHwnd(hwndTopic);
if (hdeCur && !FTopicHasSR(hdeCur))
hdeCur = NULL;
}
if (hdeCur == NULL)
continue;
/*
* Make a copy of the DE info and use THAT for text export Note:
* HdeCreate calls GenMsg fns and may put up an error box
*/
hdeCopy = HdeCreate(NULL, hdeCur, deCopy);
if (hdeCopy == NULL) {
// A bogus error to flag the error condition
wErr = wERRS_OOM;
fWithholdError = TRUE;
break;
}
hdc = GetAndSetHDC(hwndTopic, hdeCopy);
if (!hdc) {
DestroyHde(hdeCopy);
wErr = wERRS_OOM;
goto error_return;
}
// Review: I don't know why we fiddle with the Env stuff here
FEnlistEnv((HWND)(-1), hdeCopy);
FSetEnv((HWND)(-1));
qdeCopy = QdeFromGh(hdeCopy);
// Review: We copy the hwnd from hdeCur because our current hdeCopy does
// not have one. Way down in the layout code, if the Cur has an
// annotation, the hwnd will be used, (PtAnnoLim()) and therefore must
// be present. Is there a better way for PtAnnoLim to do it's job? Is this
// the right HWND to use? if not, what?
qdeCopy->hwnd = QdeFromGh(hdeCur)->hwnd;
/*
* HACK: To get this working, I am forcing the DE type here. Right
* now we have no way to distinguish, given a DE, which layout to use.
*/
qdeCopy->deType = (cDE == 0) ? deNSR : deTopic;
hte = HteNew(qdeCopy);
qdeCopy->deType = deCopy;
// DANGER: To save space, we do not check wErr until later
if (hte == NULL)
wErr = wERRS_FSReadWrite;
else {
gh = GhCopyLayoutText(qdeCopy, hte, gh, &lcbAlloc, &lcbTotal, &wErr);
DestroyHte(qdeCopy, hte);
}
RelHDC(hwndTopic, hdeCopy, hdc);
HdeDefectEnv((HWND)(-1));
// DANGER: We now check error code from WCopyLayoutText and HteNew
if (wErr != wERRS_NO) {
FSetEnv(hwndTemp);
goto error_return;
}
} /* for */
/*
* This segment of code will append the copyright string to the end
* of the copy if the copyright string exists. This code will get
* executed after the last window has been processed. NOTE: We drop
* out of the above loop with the last hdeCopy still not freeded.
*/
{
PSTR pszData; // Pointer to copied data
LPSTR szCopyright; // pointer to copyright/citation
LONG lcbCopyright;
if (hdeCopy) {
// REVIEW: popup help does not include any copyright information
if (fHelp != POPUP_HELP) {
qdeCopy = QdeFromGh(hdeCopy);
/* Take the Citation String and append it to the text copied.
* (At one point the original copyright string was to be used
* as an alternate. But that's no longer true. 09-Jul-1991 LeoN)
*/
szCopyright = QDE_HCITATION(qdeCopy)
? (LPSTR)PtrFromGh (QDE_HCITATION (qdeCopy))
: NULL;
// : QDE_RGCHCOPYRIGHT(qdeCopy);
if (szCopyright && szCopyright[0]) {
lcbCopyright = lstrlen(szCopyright);
if (lcbTotal + lcbCopyright > lcbAlloc) {
lcbAlloc = lcbTotal + lcbCopyright;
hglbNew = GlobalReAlloc(gh, (DWORD) lcbAlloc, GPTR);
if (!hglbNew) {
DestroyHde(hdeCopy);
wErr = wERRS_OOM_COPY_FAILURE;
DestroyHde(hdeCopy);
goto error_return;
}
else
gh = hglbNew;
}
pszData = (PSTR) GlobalLock(gh);
// The NULL char is added at the end of the buffer
MoveMemory(&pszData[lcbTotal], szCopyright, lcbCopyright);
lcbTotal += lcbCopyright;
GlobalUnlock(gh);
}
}
DestroyHde(hdeCopy);
}
}
FSetEnv(hwndTemp);
/* Now place the text buffer in the Clipboard.
* We shrink the buffer to one more than the length of the text, in
* order to save memory and add the NULL char. Note that the GPTR
* zero-inits memory and gives us the NULL char for free.
*
* We replace the gh on the assumption that since we are shrinking the
* allocation request, GlobalReAlloc cannot fail.
*/
gh = GlobalReAlloc(gh, (DWORD) lcbTotal + 1, GPTR);
ASSERT(gh);
if (OpenClipboard(hwnd)) {
EmptyClipboard();
SetClipboardData(CF_TEXT, gh);
CloseClipboard();
return TRUE;
}
else
wErr = wERRS_EXPORT;
error_return:
if (gh != NULL)
GlobalFree(gh);
if (!fWithholdError)
PostErrorMessage(wErr);
return(FALSE);
}
/*----------------------------------------------------------------------------+
| WCopyLayoutText(qdeCopy, hte, gh, qlcbAlloc, qlcb, qwerr) |
| |
| Purpose: |
| Append the text of the given DE's layout to the given buffer. |
| |
| Arguments: |
| qdeCopy The DE to get the text from. |
| hte The handle to layout's export-text stuff for this DE. |
| gh The handle to the clipboard buffer. |
| qlcbAlloc The current size of the clipboard buffer. This may be |
| increased by this routine. |
| qlcb The length of the existing text in the buffer. This is |
| updated by this routine to reflect the amount copied. |
| qwerr A wERR type of error code. |
| |
| Returns: |
| A GHandle to the buffer, which may be different from the gh passed. |
| The routine also modifies the above size arguments. |
| |
| Method: |
| Calls layout's text-export function and copies the resulting text to |
| the buffer. If we need more room, we expand the buffer. |
+----------------------------------------------------------------------------*/
static GH STDCALL GhCopyLayoutText(
QDE qdeCopy,
HTE hte,
GH gh,
QL qlcbAlloc,
QL qlcb,
QW qwerr
) {
LONG lcbTotal;
LONG lcbT;
LONG lcbAlloc;
LPSTR qch;
RB rbCurr;
ASSERT(qdeCopy != NULL);
ASSERT(hte != NULL);
ASSERT(gh != NULL);
ASSERT(qlcbAlloc != NULL);
ASSERT(qlcb != NULL);
lcbAlloc = *qlcbAlloc;
rbCurr = (RB) GlobalLock(gh);
rbCurr += (lcbTotal = *qlcb);
while ((qch = QchNextHte(qdeCopy, hte)) != NULL) {
lcbT = *(QL)qch;
qch += sizeof(LONG);
/*
* If initial chunk was not big enough, grab more memory.
*/
if (lcbTotal + lcbT >= lcbAlloc) {
lcbAlloc += lcbT + CLIPALLOCSIZE;
GlobalUnlock (gh);
if ((gh = GlobalReAlloc(gh, (DWORD) lcbAlloc, GPTR)) == NULL) {
*qwerr = wERRS_OOM;
return NULL;
}
rbCurr = (RB) GlobalLock(gh);
rbCurr += lcbTotal;
}
MoveMemory(rbCurr, qch, lcbT);
lcbTotal += lcbT;
rbCurr += lcbT;
}
GlobalUnlock(gh);
*qlcb = lcbTotal;
*qlcbAlloc = lcbAlloc;
*qwerr = wERRS_NO;
return gh;
}