/*********************************************************************** * GetDOSEnvironment (KERNEL.131) * * Note: the environment is allocated once, it doesn't track changes * made using the Win32 API. This shouldn't matter. * * Format of a 16-bit environment block: * ASCIIZ string 1 (xx=yy format) * ... * ASCIIZ string n * BYTE 0 * WORD 1 * ASCIIZ program name (e.g. C:\WINDOWS\SYSTEM\KRNL386.EXE) */ SEGPTR WINAPI GetDOSEnvironment16(void) { static const char ENV_program_name[] = "C:\\WINDOWS\\SYSTEM\\KRNL386.EXE"; static HGLOBAL16 handle; /* handle to the 16 bit environment */ if (!handle) { DWORD size; LPSTR p, env; p = env = GetEnvironmentStringsA(); while (*p) p += strlen(p) + 1; p++; /* skip last null */ size = (p - env) + sizeof(WORD) + sizeof(ENV_program_name); handle = GlobalAlloc16( GMEM_FIXED, size ); if (handle) { WORD one = 1; LPSTR env16 = GlobalLock16( handle ); memcpy( env16, env, p - env ); memcpy( env16 + (p - env), &one, sizeof(one)); memcpy( env16 + (p - env) + sizeof(WORD), ENV_program_name, sizeof(ENV_program_name)); GlobalUnlock16( handle ); } FreeEnvironmentStringsA( env ); } return WOWGlobalLock16( handle ); }
/************************************************************************* * DragQueryFile [SHELL.11] */ UINT16 WINAPI DragQueryFile16( HDROP16 hDrop, WORD wFile, LPSTR lpszFile, WORD wLength) { LPSTR lpDrop; UINT i = 0; LPDROPFILESTRUCT16 lpDropFileStruct = (LPDROPFILESTRUCT16) GlobalLock16(hDrop); TRACE("(%04x, %x, %p, %u)\n", hDrop,wFile,lpszFile,wLength); if(!lpDropFileStruct) goto end; lpDrop = (LPSTR) lpDropFileStruct + lpDropFileStruct->wSize; while (i++ < wFile) { while (*lpDrop++); /* skip filename */ if (!*lpDrop) { i = (wFile == 0xFFFF) ? i : 0; goto end; } } i = strlen(lpDrop); if (!lpszFile ) goto end; /* needed buffer size */ lstrcpynA (lpszFile, lpDrop, wLength); end: GlobalUnlock16(hDrop); return i; }
/****************************************************************************** * This method is part of the ILockBytes interface. * * It writes the specified bytes at the specified offset. * position. If the array is too small, it will be resized. * * See the documentation of ILockBytes for more info. */ HRESULT CDECL HGLOBALLockBytesImpl16_WriteAt( ILockBytes16* iface, ULARGE_INTEGER ulOffset, /* [in] */ const void* pv, /* [in][size_is] */ ULONG cb, /* [in] */ ULONG* pcbWritten) /* [out] */ { HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; void* supportBuffer; ULARGE_INTEGER newSize; ULONG bytesWritten = 0; TRACE("(%p,%d,%p,%d,%p)\n",This,ulOffset.u.LowPart,pv,cb,pcbWritten); /* * If the caller is not interested in the number of bytes written, * we use another buffer to avoid "if" statements in the code. */ if (pcbWritten == 0) pcbWritten = &bytesWritten; if (cb == 0) return S_OK; newSize.u.HighPart = 0; newSize.u.LowPart = ulOffset.u.LowPart + cb; /* * Verify if we need to grow the stream */ if (newSize.u.LowPart > This->byteArraySize.u.LowPart) { /* grow stream */ if (HGLOBALLockBytesImpl16_SetSize(iface, newSize) == STG_E_MEDIUMFULL) return STG_E_MEDIUMFULL; } /* * Lock the buffer in position and copy the data. */ supportBuffer = GlobalLock16(This->supportHandle); memcpy((char *) supportBuffer + ulOffset.u.LowPart, pv, cb); /* * Return the number of bytes written. */ *pcbWritten = cb; /* * Cleanup */ GlobalUnlock16(This->supportHandle); return S_OK; }
static HICON convert_icon_to_32( HICON16 icon16 ) { CURSORICONINFO *info = GlobalLock16( icon16 ); void *and_bits = info + 1; void *xor_bits = (BYTE *)and_bits + info->nHeight * 2 * ((info->nWidth + 15) / 16); HICON ret = CreateIcon( 0, info->nWidth, info->nHeight, info->bPlanes, info->bBitsPerPixel, and_bits, xor_bits ); GlobalUnlock16( icon16 ); return ret; }
/************************************************************************* * DragQueryPoint [SHELL.13] */ BOOL16 WINAPI DragQueryPoint16(HDROP16 hDrop, POINT16 *p) { LPDROPFILESTRUCT16 lpDropFileStruct; BOOL16 bRet; TRACE("\n"); lpDropFileStruct = (LPDROPFILESTRUCT16) GlobalLock16(hDrop); memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT16)); bRet = lpDropFileStruct->fInNonClientArea; GlobalUnlock16(hDrop); return bRet; }
/************************************************************************* * FindClose (KERNEL.415) */ BOOL16 WINAPI FindClose16( HANDLE16 handle ) { HANDLE *ptr; if ((handle == INVALID_HANDLE_VALUE16) || !(ptr = GlobalLock16( handle ))) { SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } FindClose( *ptr ); GlobalUnlock16( handle ); GlobalFree16( handle ); return TRUE; }
/************************************************************************* * FindNextFile (KERNEL.414) */ BOOL16 WINAPI FindNextFile16( HANDLE16 handle, WIN32_FIND_DATAA *data ) { HANDLE *ptr; BOOL ret = FALSE; if ((handle == INVALID_HANDLE_VALUE16) || !(ptr = GlobalLock16( handle ))) { SetLastError( ERROR_INVALID_HANDLE ); return ret; } ret = FindNextFileA( *ptr, data ); GlobalUnlock16( handle ); return ret; }
/****************************************************************** * create_metafile16 * * Create a 16-bit metafile from a 32-bit one. The 32-bit one is deleted. */ static HMETAFILE16 create_metafile16( HMETAFILE hmf ) { UINT size; HMETAFILE16 hmf16; if (!hmf) return 0; size = GetMetaFileBitsEx( hmf, 0, NULL ); hmf16 = GlobalAlloc16( GMEM_MOVEABLE, size ); if (hmf16) { void *buffer = GlobalLock16( hmf16 ); GetMetaFileBitsEx( hmf, size, buffer ); GlobalUnlock16( hmf16 ); } DeleteMetaFile( hmf ); return hmf16; }
/************************************************************************* * FindFirstFile (KERNEL.413) */ HANDLE16 WINAPI FindFirstFile16( LPCSTR path, WIN32_FIND_DATAA *data ) { HGLOBAL16 h16; HANDLE handle, *ptr; if (!(h16 = GlobalAlloc16( GMEM_MOVEABLE, sizeof(handle) ))) return INVALID_HANDLE_VALUE16; ptr = GlobalLock16( h16 ); *ptr = handle = FindFirstFileA( path, data ); GlobalUnlock16( h16 ); if (handle == INVALID_HANDLE_VALUE) { GlobalFree16( h16 ); h16 = INVALID_HANDLE_VALUE16; } return h16; }
/****************************************************************************** * OleMetaFilePictFromIconAndLabel (OLE2.56) * * Returns a global memory handle to a metafile which contains the icon and * label given. * I guess the result of that should look somehow like desktop icons. * If no hIcon is given, we load the icon via lpszSourceFile and iIconIndex. * This code might be wrong at some places. */ HGLOBAL16 WINAPI OleMetaFilePictFromIconAndLabel16( HICON16 hIcon, LPCOLESTR16 lpszLabel, LPCOLESTR16 lpszSourceFile, UINT16 iIconIndex ) { METAFILEPICT16 *mf16; HGLOBAL16 hmf16; HMETAFILE hmf; INT mfSize; HDC hdc; if (!hIcon) { if (lpszSourceFile) { HINSTANCE16 hInstance = LoadLibrary16(lpszSourceFile); /* load the icon at index from lpszSourceFile */ hIcon = HICON_16(LoadIconA(HINSTANCE_32(hInstance), (LPCSTR)(DWORD)iIconIndex)); FreeLibrary16(hInstance); } else return 0; } FIXME("(%04x, '%s', '%s', %d): incorrect metrics, please try to correct them !\n", hIcon, lpszLabel, lpszSourceFile, iIconIndex); hdc = CreateMetaFileW(NULL); DrawIcon(hdc, 0, 0, HICON_32(hIcon)); /* FIXME */ TextOutA(hdc, 0, 0, lpszLabel, 1); /* FIXME */ hmf = CloseMetaFile(hdc); hmf16 = GlobalAlloc16(0, sizeof(METAFILEPICT16)); mf16 = (METAFILEPICT16 *)GlobalLock16(hmf16); mf16->mm = MM_ANISOTROPIC; mf16->xExt = 20; /* FIXME: bogus */ mf16->yExt = 20; /* dito */ mfSize = GetMetaFileBitsEx(hmf, 0, 0); mf16->hMF = GlobalAlloc16(GMEM_MOVEABLE, mfSize); if(mf16->hMF) { GetMetaFileBitsEx(hmf, mfSize, GlobalLock16(mf16->hMF)); GlobalUnlock16(mf16->hMF); } return hmf16; }
static BOOL PRINTDLG_CreateDevNames16(HGLOBAL16 *hmem, const char* DeviceDriverName, const char* DeviceName, const char* OutputPort) { long size; char* pDevNamesSpace; char* pTempPtr; LPDEVNAMES lpDevNames; char buf[260]; DWORD dwBufLen = sizeof(buf); size = strlen(DeviceDriverName) + 1 + strlen(DeviceName) + 1 + strlen(OutputPort) + 1 + sizeof(DEVNAMES); if(*hmem) *hmem = GlobalReAlloc16(*hmem, size, GMEM_MOVEABLE); else *hmem = GlobalAlloc16(GMEM_MOVEABLE, size); if (*hmem == 0) return FALSE; pDevNamesSpace = GlobalLock16(*hmem); lpDevNames = (LPDEVNAMES) pDevNamesSpace; pTempPtr = pDevNamesSpace + sizeof(DEVNAMES); strcpy(pTempPtr, DeviceDriverName); lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace; pTempPtr += strlen(DeviceDriverName) + 1; strcpy(pTempPtr, DeviceName); lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace; pTempPtr += strlen(DeviceName) + 1; strcpy(pTempPtr, OutputPort); lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace; GetDefaultPrinterA(buf, &dwBufLen); lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0; GlobalUnlock16(*hmem); return TRUE; }
/********************************************************************** * CreatePQ (GDI.230) * */ HPQ16 WINAPI CreatePQ16(INT16 size) { #if 0 HGLOBAL16 hpq = 0; WORD tmp_size; LPWORD pPQ; tmp_size = size << 2; if (!(hpq = GlobalAlloc16(GMEM_SHARE|GMEM_MOVEABLE, tmp_size + 8))) return 0xffff; pPQ = GlobalLock16(hpq); *pPQ++ = 0; *pPQ++ = tmp_size; *pPQ++ = 0; *pPQ++ = 0; GlobalUnlock16(hpq); return (HPQ16)hpq; #else FIXME("(%d): stub\n",size); return 1; #endif }
void SNOOP16_RegisterDLL(HMODULE16 hModule,LPCSTR name) { SNOOP16_DLL **dll = &(firstdll); char *s; if (!TRACE_ON(snoop)) return; TRACE("hmod=%x, name=%s\n", hModule, name); if (!snr) { xsnr=GLOBAL_Alloc(GMEM_ZEROINIT,2*sizeof(*snr),0,WINE_LDT_FLAGS_CODE|WINE_LDT_FLAGS_32BIT); snr = GlobalLock16(xsnr); snr[0].pushbp = 0x5566; snr[0].pusheax = 0x50; snr[0].pushax = 0x5066; snr[0].pushl = 0x68; snr[0].realfun = (DWORD)SNOOP16_Entry; snr[0].lcall = 0x9a; snr[0].callfromregs = (DWORD)__wine_call_from_16_regs; snr[0].seg = wine_get_cs(); snr[0].lret = 0xcb66; snr[1].pushbp = 0x5566; snr[1].pusheax = 0x50; snr[1].pushax = 0x5066; snr[1].pushl = 0x68; snr[1].realfun = (DWORD)SNOOP16_Return; snr[1].lcall = 0x9a; snr[1].callfromregs = (DWORD)__wine_call_from_16_regs; snr[1].seg = wine_get_cs(); snr[1].lret = 0xcb66; } while (*dll) { if ((*dll)->hmod == hModule) { /* another dll, loaded at the same address */ GlobalUnlock16((*dll)->funhandle); GlobalFree16((*dll)->funhandle); break; } dll = &((*dll)->next); } if (*dll) *dll = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *dll, sizeof(SNOOP16_DLL)+strlen(name)); else *dll = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SNOOP16_DLL)+strlen(name)); (*dll)->next = NULL; (*dll)->hmod = hModule; if ((s=strrchr(name,'\\'))) name = s+1; strcpy( (*dll)->name, name ); if ((s=strrchr((*dll)->name,'.'))) *s='\0'; (*dll)->funhandle = GlobalHandleToSel16(GLOBAL_Alloc(GMEM_ZEROINIT,65535,0,WINE_LDT_FLAGS_CODE)); (*dll)->funs = GlobalLock16((*dll)->funhandle); if (!(*dll)->funs) { HeapFree(GetProcessHeap(),0,*dll); FIXME("out of memory\n"); return; } }
void WINAPI XMS_Handler( CONTEXT86 *context ) { switch(AH_reg(context)) { case 0x00: /* Get XMS version number */ TRACE("get XMS version number\n"); SET_AX( context, 0x0200 ); /* 2.0 */ SET_BX( context, 0x0000 ); /* internal revision */ SET_DX( context, 0x0001 ); /* HMA exists */ break; case 0x08: /* Query Free Extended Memory */ { MEMORYSTATUS status; TRACE("query free extended memory\n"); GlobalMemoryStatus( &status ); SET_DX( context, status.dwAvailVirtual >> 10 ); SET_AX( context, status.dwAvailVirtual >> 10 ); TRACE("returning largest %dK, total %dK\n", AX_reg(context), DX_reg(context)); } break; case 0x09: /* Allocate Extended Memory Block */ TRACE("allocate extended memory block (%dK)\n", DX_reg(context)); SET_DX( context, GlobalAlloc16(GMEM_MOVEABLE, (DWORD)DX_reg(context)<<10) ); SET_AX( context, DX_reg(context) ? 1 : 0 ); if (!DX_reg(context)) SET_BL( context, 0xA0 ); /* out of memory */ break; case 0x0a: /* Free Extended Memory Block */ TRACE("free extended memory block %04x\n",DX_reg(context)); if(!DX_reg(context) || GlobalFree16(DX_reg(context))) { SET_AX( context, 0 ); /* failure */ SET_BL( context, 0xa2 ); /* invalid handle */ } else SET_AX( context, 1 ); /* success */ break; case 0x0b: /* Move Extended Memory Block */ { MOVESTRUCT*move=CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Esi); BYTE*src,*dst; TRACE("move extended memory block\n"); src=XMS_Offset(&move->Source); dst=XMS_Offset(&move->Dest); memcpy(dst,src,move->Length); if (move->Source.Handle) GlobalUnlock16(move->Source.Handle); if (move->Dest.Handle) GlobalUnlock16(move->Dest.Handle); break; } case 0x88: /* Query Any Free Extended Memory */ { MEMORYSTATUS status; SYSTEM_INFO info; TRACE("query any free extended memory\n"); GlobalMemoryStatus( &status ); GetSystemInfo( &info ); context->Eax = status.dwAvailVirtual >> 10; context->Edx = status.dwAvailVirtual >> 10; context->Ecx = (DWORD)info.lpMaximumApplicationAddress; SET_BL( context, 0 ); /* No errors. */ TRACE("returning largest %dK, total %dK, highest 0x%x\n", context->Eax, context->Edx, context->Ecx); } break; default: INT_BARF( context, 0x31 ); SET_AX( context, 0x0000 ); /* failure */ SET_BL( context, 0x80 ); /* function not implemented */ break; } }
/********************************************************************** * K32WOWGlobalUnlock16 (KERNEL32.61) */ BOOL WINAPI K32WOWGlobalUnlock16( WORD hMem ) { return (BOOL)GlobalUnlock16( (HGLOBAL16)hMem ); }
/*********************************************************************** * PRINTDLG_WMInitDialog [internal] */ static LRESULT PRINTDLG_WMInitDialog16(HWND hDlg, WPARAM wParam, PRINT_PTRA16* ptr16) { PRINT_PTRA *PrintStructures = &ptr16->print32; LPPRINTDLG16 lppd = ptr16->lpPrintDlg16; DEVNAMES *pdn; DEVMODEA *pdm; char *name = NULL; UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4; /* load Collate ICONs */ PrintStructures->hCollateIcon = LoadIconA(COMDLG32_hInstance, "PD32_COLLATE"); PrintStructures->hNoCollateIcon = LoadIconA(COMDLG32_hInstance, "PD32_NOCOLLATE"); if(PrintStructures->hCollateIcon == 0 || PrintStructures->hNoCollateIcon == 0) { ERR("no icon in resourcefile\n"); COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE); EndDialog(hDlg, FALSE); } /* load Paper Orientation ICON */ /* FIXME: not implemented yet */ /* * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message * must be registered and the Help button must be shown. */ if (lppd->Flags & PD_SHOWHELP) { if((PrintStructures->HelpMessageID = RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) { COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL); return FALSE; } } else PrintStructures->HelpMessageID = 0; if (!(lppd->Flags & PD_PRINTSETUP)) { /* We have a print quality combo box. What shall we do? */ if (GetDlgItem(hDlg,cmb1)) { char buf [20]; FIXME("Print quality only displaying currently.\n"); pdm = GlobalLock16(lppd->hDevMode); if(pdm) { switch (pdm->u1.s1.dmPrintQuality) { case DMRES_HIGH : strcpy(buf,"High"); break; case DMRES_MEDIUM : strcpy(buf,"Medium"); break; case DMRES_LOW : strcpy(buf,"Low"); break; case DMRES_DRAFT : strcpy(buf,"Draft"); break; case 0 : strcpy(buf,"Default"); break; default : sprintf(buf,"%ddpi",pdm->u1.s1.dmPrintQuality); break; } GlobalUnlock16(lppd->hDevMode); } else strcpy(buf,"Default"); SendDlgItemMessageA(hDlg,cmb1,CB_ADDSTRING,0,(LPARAM)buf); SendDlgItemMessageA(hDlg,cmb1,CB_SETCURSEL,0,0); EnableWindow(GetDlgItem(hDlg,cmb1),FALSE); } } /* FIXME: I allow more freedom than either Win95 or WinNT, * which do not agree to what errors should be thrown or not * in case nToPage or nFromPage is out-of-range. */ if (lppd->nMaxPage < lppd->nMinPage) lppd->nMaxPage = lppd->nMinPage; if (lppd->nMinPage == lppd->nMaxPage) lppd->Flags |= PD_NOPAGENUMS; if (lppd->nToPage < lppd->nMinPage) lppd->nToPage = lppd->nMinPage; if (lppd->nToPage > lppd->nMaxPage) lppd->nToPage = lppd->nMaxPage; if (lppd->nFromPage < lppd->nMinPage) lppd->nFromPage = lppd->nMinPage; if (lppd->nFromPage > lppd->nMaxPage) lppd->nFromPage = lppd->nMaxPage; /* If the printer combo box is in the dialog, fill it */ if (GetDlgItem(hDlg,comboID)) { /* Fill Combobox */ pdn = GlobalLock16(lppd->hDevNames); pdm = GlobalLock16(lppd->hDevMode); if(pdn) name = (char*)pdn + pdn->wDeviceOffset; else if(pdm) name = (char*)pdm->dmDeviceName; PRINTDLG_SetUpPrinterListComboA(hDlg, comboID, name); if(pdm) GlobalUnlock16(lppd->hDevMode); if(pdn) GlobalUnlock16(lppd->hDevNames); /* Now find selected printer and update rest of dlg */ name = HeapAlloc(GetProcessHeap(),0,256); if (GetDlgItemTextA(hDlg, comboID, name, 255)) PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures); } else { /* else just use default printer */ char name[200]; DWORD dwBufLen = sizeof(name); BOOL ret = GetDefaultPrinterA(name, &dwBufLen); if (ret) PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures); else FIXME("No default printer found, expect problems!\n"); } HeapFree(GetProcessHeap(),0,name); return TRUE; }
/****************************************************************** * MF_ReleaseMetaHeader16 * * Releases METAHEADER associated with HMETAFILE16 */ static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf ) { return GlobalUnlock16( hmf ); }
/*********************************************************************** * EMFDRV_CreateBrushIndirect */ DWORD EMFDRV_CreateBrushIndirect( DC *dc, HBRUSH hBrush ) { DWORD index = 0; LOGBRUSH logbrush; if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return 0; switch (logbrush.lbStyle) { case BS_SOLID: case BS_HATCHED: case BS_NULL: { EMRCREATEBRUSHINDIRECT emr; emr.emr.iType = EMR_CREATEBRUSHINDIRECT; emr.emr.nSize = sizeof(emr); emr.ihBrush = index = EMFDRV_AddHandleDC( dc ); emr.lb = logbrush; if(!EMFDRV_WriteRecord( dc, &emr.emr )) index = 0; } break; case BS_DIBPATTERN: { EMRCREATEDIBPATTERNBRUSHPT *emr; DWORD bmSize, biSize, size; BITMAPINFO *info = GlobalLock16(logbrush.lbHatch); if (info->bmiHeader.biCompression) bmSize = info->bmiHeader.biSizeImage; else bmSize = DIB_GetDIBImageBytes(info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biBitCount); biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush.lbColor)); size = sizeof(EMRCREATEDIBPATTERNBRUSHPT) + biSize + bmSize; emr = HeapAlloc( GetProcessHeap(), 0, size ); if(!emr) break; emr->emr.iType = EMR_CREATEDIBPATTERNBRUSHPT; emr->emr.nSize = size; emr->ihBrush = index = EMFDRV_AddHandleDC( dc ); emr->iUsage = LOWORD(logbrush.lbColor); emr->offBmi = sizeof(EMRCREATEDIBPATTERNBRUSHPT); emr->cbBmi = biSize; emr->offBits = sizeof(EMRCREATEDIBPATTERNBRUSHPT) + biSize; memcpy((char *)emr + sizeof(EMRCREATEDIBPATTERNBRUSHPT), info, biSize + bmSize ); if(!EMFDRV_WriteRecord( dc, &emr->emr )) index = 0; HeapFree( GetProcessHeap(), 0, emr ); GlobalUnlock16(logbrush.lbHatch); } break; case BS_PATTERN: FIXME("Unsupported style %x\n", logbrush.lbStyle); break; default: FIXME("Unknown style %x\n", logbrush.lbStyle); break; } return index; }
/****************************************************************************** * This method is part of the ILockBytes interface. * * It reads a block of information from the byte array at the specified * offset. * * See the documentation of ILockBytes for more info. */ HRESULT CDECL HGLOBALLockBytesImpl16_ReadAt( ILockBytes16* iface, ULARGE_INTEGER ulOffset, /* [in] */ void* pv, /* [out][length_is][size_is] */ ULONG cb, /* [in] */ ULONG* pcbRead) /* [out] */ { HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; void* supportBuffer; ULONG bytesReadBuffer = 0; ULONG bytesToReadFromBuffer; TRACE("(%p,%d,%p,%d,%p)\n",This,ulOffset.u.LowPart,pv,cb,pcbRead); /* * If the caller is not interested in the number of bytes read, * we use another buffer to avoid "if" statements in the code. */ if (pcbRead == 0) pcbRead = &bytesReadBuffer; /* * Make sure the offset is valid. */ if (ulOffset.u.LowPart > This->byteArraySize.u.LowPart) return E_FAIL; /* * Using the known size of the array, calculate the number of bytes * to read. */ bytesToReadFromBuffer = min(This->byteArraySize.u.LowPart - ulOffset.u.LowPart, cb); /* * Lock the buffer in position and copy the data. */ supportBuffer = GlobalLock16(This->supportHandle); memcpy(pv, (char *) supportBuffer + ulOffset.u.LowPart, bytesToReadFromBuffer); /* * Return the number of bytes read. */ *pcbRead = bytesToReadFromBuffer; /* * Cleanup */ GlobalUnlock16(This->supportHandle); /* * The function returns S_OK if the specified number of bytes were read * or the end of the array was reached. * It returns STG_E_READFAULT if the number of bytes to read does not equal * the number of bytes actually read. */ if(*pcbRead == cb) return S_OK; return STG_E_READFAULT; }