/**************************************************************************** PARAMETERS: cache - cache to free REMARKS: Frees directory cache structure {secret} ****************************************************************************/ static void freeFontCache( dirCache *cache) { size_t i; for (i = 0; i < cache->filesCnt; i++) { PM_free(cache->files[i].fileName); PM_free(cache->files[i].familyName); } PM_free(cache->files); }
int main(void) { PM_HWND hwndConsole; ulong stateSize; void *stateBuf; FILE *f; /* Allocate a buffer to save console state and save the state */ hwndConsole = PM_openConsole(0,0,0,0,0,true); stateSize = PM_getConsoleStateSize(); if ((stateBuf = PM_malloc(stateSize)) == NULL) { PM_closeConsole(hwndConsole); printf("Unable to allocate console state buffer!\n"); return -1; } PM_saveConsoleState(stateBuf,0); /* Restore the console state on exit */ PM_restoreConsoleState(stateBuf,0); PM_closeConsole(hwndConsole); /* Write the saved console state buffer to disk */ if ((f = fopen("/etc/pmsave.dat","wb")) == NULL) printf("Unable to open /etc/pmsave.dat for writing!\n"); else { fwrite(&stateSize,1,sizeof(stateSize),f); fwrite(stateBuf,1,stateSize,f); fclose(f); printf("Console state successfully saved to /etc/pmsave.dat\n"); } PM_free(stateBuf); return 0; }
/**************************************************************************** REMARKS: Free a page aligned and page sized block of memory ****************************************************************************/ void PMAPI PM_freePage( void *p) { pageblock *block; /* First find the page block that this page belongs to */ for (block = pageBlocks; block != NULL; block = block->next) { if (p >= block->freeListStart && p <= block->freeListEnd) break; } CHECK(block != NULL); /* Now free the block by adding it to the free list */ FREELIST_NEXT(p) = block->freeList; block->freeList = p; if (++block->freeCount == PAGES_PER_BLOCK) { /* If all pages in the page block are now free, free the entire * page block itself. */ if (block == pageBlocks) { /* Delete from head */ pageBlocks = block->next; if (block->next) block->next->prev = NULL; } else { /* Delete from middle of list */ CHECK(block->prev != NULL); block->prev->next = block->next; if (block->next) block->next->prev = block->prev; } PM_free(block); } }
int main(void) { int i; ulong allocs; char *p,*pa[MAXALLOC]; PM_HWND hwndConsole; hwndConsole = PM_openConsole(0,0,0,0,0,true); for (allocs = i = 0; i < MAXALLOC; i++) { if ((pa[i] = PM_malloc(10*1024)) != 0) { /* in 10k blocks */ p = pa[allocs]; memset(p, 0, 10*1024); /* touch every byte */ *p = 'x'; /* do something, anything with */ p[1023] = 'y'; /* the allocated memory */ allocs++; printf("Allocated %lu bytes\r", 10*(allocs << 10)); } else break; if (PM_kbhit() && (PM_getch() == 0x1B)) break; } PM_closeConsole(hwndConsole); printf("\n\nAllocated total of %lu bytes\n", 10 * (allocs << 10)); for (i = allocs-1; i >= 0; i--) PM_free(pa[i]); return 0; }
void PMAPI PM_freeShared(void *ptr) { // TODO: Free the shared memory block. This will be called in the context // of the original calling process that allocated the shared // memory with PM_mallocShared. Simply call free if you do not // need this. PM_free(ptr); }
/**************************************************************************** PARAMETERS: c - structure to free REMARKS: Recursively frees fontEnumCache data structure. {secret} ****************************************************************************/ static void freeFontEnumCache( fontEnumCache *c) { if (c == NULL) return; freeFontEnumCache(c->next); PM_free(c); }
/**************************************************************************** REMARKS: Frees the internal data structures allocated during the detection process ****************************************************************************/ void MGLAPI SNAPVBE_destroyInstance( void *data) { if (data) { SNAP_unload((SNAP_data*)data); PM_free(data); } }
/**************************************************************************** REMARKS: VxD implementation of the ANSI C fclose function. ****************************************************************************/ int fclose( FILE *f) { fflush(f); _OS2Close((HFILE)f->handle); PM_free(f); return 0; }
/**************************************************************************** REMARKS: Free a block of shared memory. ****************************************************************************/ void PMAPI PM_freeShared( void *ptr) { /* TODO: Free the shared memory block. This will be called in the context */ /* of the original calling process that allocated the shared */ /* memory with PM_mallocShared. Simply call PM_free if you do not */ /* need this. */ PM_free(ptr); }
/**************************************************************************** PARAMETERS: dc - Device context to destroy RETURNS: True if the context was destroyed, false on error. REMARKS: Searches for the display device context in the list of currently allocated contexts, and destroys it if it exists. If this is the last display device context, then we also shut down the graphics mode and restore the original graphics mode. {secret} ****************************************************************************/ ibool _MGL_destroyDisplayDC( MGLDC *dc) { MGLDC *prev; PM_HWND hwndConsole; if (!dc) { FATALERROR(grInvalidDC); return false; } if (DEV.dispDCList->count == 1) { /* There is only one active display context left, so restore * the original display mode and destroy the entire display * device context list */ if (dc != _LST_first(DEV.dispDCList)) { FATALERROR(grInvalidDC); return false; } /* Save the console window handle for later as the DC structure * is destroyed before we close the console itself. */ hwndConsole = (PM_HWND)dc->v->d.hwnd; dc->v->d.restoreTextMode(dc); _MGL_freeInternalDCVars(dc); dc->v->d.destroy(dc); _LST_destroy(DEV.dispDCList,_LST_freeNode); DEV.dispDCList = NULL; /* Restore the console state and close it */ if (DEV.stateBuf) { PM_restoreConsoleState(DEV.stateBuf,hwndConsole); PM_free(DEV.stateBuf); DEV.stateBuf = NULL; PM_closeConsole(hwndConsole); } /* We are no longer in Windows full screen mode but on the desktop */ if (_MGL_consoleSupport) _MS_setDisplayDC(NULL); } else { /* There is more than one active display context, so simply * remove the current one from the list and destroy it. */ if ((prev = _LST_findNode(DEV.dispDCList,dc)) == NULL) { FATALERROR(grInvalidDC); return false; } _MGL_freeInternalDCVars(dc); dc->v->d.destroy(dc); _LST_removeNext(DEV.dispDCList,prev); _LST_freeNode(dc); } return true; }
/**************************************************************************** REMARKS: VxD implementation of the ANSI C fclose function. ****************************************************************************/ int fclose( FILE *f) { WORD error; if (initComplete) R0_CloseFile((HANDLE)f->handle,&error); else i_close(f->handle); PM_free(f); return 0; }
/**************************************************************************** PARAMETERS: dc - Device context to destroy REMARKS: Destroys all common internal data structures that need to be destroyed with the ****************************************************************************/ static void _MGL_freeInternalDCVars( MGLDC *dc) { if (dc->clipRegionUser) MGL_freeRegion(dc->clipRegionUser); if (dc->clipRegionScreen) MGL_freeRegion(dc->clipRegionScreen); if (dc->visRegionWM) MGL_freeRegion(dc->visRegionWM); if (dc->visRegionWin) MGL_freeRegion(dc->visRegionWin); PM_free(dc->colorTab); }
PRIVATE void MGLAPI destroyDC(MGLDC *dc) /**************************************************************************** * * Function: destroyDC * Parameters: dc - Device context * * Description: Destroys all internal memory allocated by the device * context. * ****************************************************************************/ { if (dc->ownMemory) PM_free(dc->surface); }
void MGLAPI XWINDC_destroyInstance(void *data) /**************************************************************************** * * Function: XWIN8_destroyInstance * * Description: Frees the internal data structures allocated during the * detection process * ****************************************************************************/ { if(data){ // XDestroyWindow(dpy, ((XWIN8_data*)data)->w); PM_free(data); } }
void VBEAPI VBE_freePMCode(void) /**************************************************************************** * * Function: VBE_freePMCode * * Description: This routine frees the protected mode code blocks that * we copied from the VBE 2.0 interface. This routine must * be after you have finished graphics processing to free up * the memory occupied by the routines. This is necessary * because the PM info memory block must be re-copied after * every video mode set from the VBE 2.0 implementation. * ****************************************************************************/ { if (state->pmInfo) { if (VBE_shared) PM_freeShared(state->pmInfo); else PM_free(state->pmInfo); state->pmInfo = NULL; state->pmInfo32 = NULL; } }
void PMAPI PM_freeShared(void *ptr) { PM_free(ptr); }
/**************************************************************************** REMARKS: Does the hard work to create the actual display device context. ****************************************************************************/ static MGLDC * _MGL_createDisplayDC( int mode, int virtualX, int virtualY, int numBuffers, ibool stereo, int refreshRate) { MGLDC *dc; driverent *entry; modeent *me = &DEV.availableModes[mode]; PM_HWND hwndConsole = (PM_HWND)NULL; /* Check if the mode is currently available */ __MGL_result = grOK; if (mode >= DEV.numModes || DEV.availableModes[mode].driver == 0xFF) { SETERROR(grInvalidMode); return NULL; } _MGL_destroyCurrentMode(); /* Allocate memory for the new DC */ if ((dc = _LST_newNode(sizeof(MGLDC))) == NULL) { FATALERROR(grNoMem); return NULL; } /* The display device list is currently empty, so create the new * list and start the specified graphics mode */ if ((DEV.dispDCList = _LST_create()) == NULL) { FATALERROR(grNoMem); goto Error; } /* Open a new fullscreen console for the mode, and save it's state */ DEV.stateBuf = NULL; if (_MGL_consoleSupport && (GET_CURRENT_DEVICE() == 0)) { hwndConsole = PM_openConsole((PM_HWND)_MGL_hwndFullScreen,GET_CURRENT_DEVICE(),me->xRes,me->yRes,me->bits,true); if ((DEV.stateBuf = PM_malloc(PM_getConsoleStateSize())) == NULL) { FATALERROR(grNoMem); goto Error; } PM_saveConsoleState(DEV.stateBuf,hwndConsole); } /* Now intialise the driver */ entry = &DEV.driverTable[me->driver]; if (!_MGL_initDC(dc,entry,me,(MGL_HWND)hwndConsole,virtualX,virtualY,numBuffers,stereo,refreshRate)) goto Error; /* Set the suspend application callback for the console */ PM_setSuspendAppCallback(_MGL_suspendAppProc); /* Set up the mouse cursor */ if (_MGL_consoleSupport) { _MS_setDisplayDC(dc); MS_setCursor(MGL_DEF_CURSOR); MS_moveTo(dc->mi.xRes/2,dc->mi.yRes/2); } /* Now clear the device page */ MGL_makeCurrentDC(dc); MGL_clearDevice(); /* And clear the event queue of any extraneous events */ if (_MGL_consoleSupport) { EVT_flush(EVT_EVERYEVT); } /* Add the new DC to the start of the DC chain */ RESET_DEFAULT_CW(); _LST_addToHead(DEV.dispDCList,dc); return dc; Error: if (hwndConsole) { if (DEV.stateBuf) { PM_restoreConsoleState(DEV.stateBuf,hwndConsole); PM_free(DEV.stateBuf); DEV.stateBuf = NULL; } PM_closeConsole(hwndConsole); } DEV.fullScreen = false; if (DEV.dispDCList && DEV.dispDCList->count == 0) { _LST_destroy(DEV.dispDCList,_LST_freeNode); DEV.dispDCList = NULL; } _LST_freeNode(dc); return NULL; }
/**************************************************************************** REMARKS: VxD implementation of the ANSI C fopen function. ****************************************************************************/ FILE * fopen( const char *filename, const char *mode) { FILE *f = PM_malloc(sizeof(FILE)); long oldpos; if (f) { f->offset = 0; f->text = (mode[1] == 't' || mode[2] == 't'); f->writemode = (mode[0] == 'w') || (mode[0] == 'a'); if (initComplete) { WORD omode,error; BYTE action; if (mode[0] == 'r') { omode = OPEN_ACCESS_READONLY | OPEN_SHARE_COMPATIBLE; action = ACTION_IFEXISTS_OPEN | ACTION_IFNOTEXISTS_FAIL; } else if (mode[0] == 'w') { omode = OPEN_ACCESS_WRITEONLY | OPEN_SHARE_COMPATIBLE; action = ACTION_IFEXISTS_TRUNCATE | ACTION_IFNOTEXISTS_CREATE; } else { omode = OPEN_ACCESS_READWRITE | OPEN_SHARE_COMPATIBLE; action = ACTION_IFEXISTS_OPEN | ACTION_IFNOTEXISTS_CREATE; } f->handle = (int)R0_OpenCreateFile(false,(char*)filename,omode,ATTR_NORMAL,action,0,&error,&action); if (f->handle == 0) { PM_free(f); return NULL; } f->filesize = R0_GetFileSize((HANDLE)f->handle,&error); if (mode[0] == 'a') fseek(f,0,2); } else { int oflag,pmode; if (mode[0] == 'r') { pmode = _S_IREAD; oflag = _O_RDONLY; } else if (mode[0] == 'w') { pmode = _S_IWRITE; oflag = _O_WRONLY | _O_CREAT | _O_TRUNC; } else { pmode = _S_IWRITE; oflag = _O_RDWR | _O_CREAT | _O_APPEND; } if (f->text) oflag |= _O_TEXT; else oflag |= _O_BINARY; if ((f->handle = i_open(filename,oflag,pmode)) == -1) { PM_free(f); return NULL; } oldpos = i_lseek(f->handle,0,1); f->filesize = i_lseek(f->handle,0,2); i_lseek(f->handle,oldpos,0); } } return f; }
/**************************************************************************** PARAMETERS: path - directory with font file filename - filename of the font file cache - local cache for one directory REMARKS: Updates cache entry for given font file. If such file is not in the cache, loads it with MGL_openFontLib and extracts information about font library type, family and face from it. A font is marked as bold if its name ends with " Bold", as italic if it ends with " Italic". Suffixes are cumulative. Family name is face name with recognized suffixes stripped off. For example, cache entry for font "Arial Bold Italic" will read "family is Arial, face is bold and italic". {secret} ****************************************************************************/ static void enumFontFile( const char *path, const char *filename, dirCache *cache) { char fullname[PM_MAX_PATH]; font_lib_t *fontLib; fileCache *entry; ibool isNewer; ibool foundSuffix; #if 0 // TODO: missing PM_getFileTime under Unix and DOS PM_time time; long ytimef, ytimec; #endif char *buf; size_t buflen; strcpy(fullname, path); PM_backslash(fullname); strcat(fullname, filename); /* Try to find entry in cache: */ entry = (fileCache*) bsearch(filename, cache->files, cache->filesCnt, sizeof(fileCache), searchFileCache); isNewer = (entry == NULL); #if 0 // TODO: missing PM_getFileTime under Unix and DOS if (!isNewer && PM_getFileTime(fullname, true, &time)) { ytimef = time.sec + 60 * (time.min + 60 * (time.hour + 24 * (time.day + 31 * time.mon))); ytimec = cache->timestamp.sec + 60 * (cache->timestamp.min + 60 * ( cache->timestamp.hour + 24 * (cache->timestamp.day + 31 * cache->timestamp.mon))); isNewer = time.year > cache->timestamp.year || (time.year == cache->timestamp.year && ytimef > ytimec); } #endif if (!isNewer) { cache->validCnt++; entry->exists = true; return; } /* Nothing in cache, we have to open the font: */ fontLib = MGL_openFontLib(fullname); if (fontLib == NULL) return; if (entry == NULL) { if (cache->filesCnt % CACHE_BLOCK_SIZE == 0) { cache->filesBlocks++; cache->files = PM_realloc(cache->files, sizeof(fileCache) * cache->filesBlocks * CACHE_BLOCK_SIZE); } entry = cache->files + cache->filesCnt; cache->filesCnt++; } else { PM_free(entry->fileName); PM_free(entry->familyName); } /* Try to determine family name and face type from facename: */ if ((entry->fileName = PM_malloc(strlen(filename) + 1)) == NULL) FATALERROR(grNoMem); strcpy(entry->fileName, filename); entry->fontLibType = fontLib->fontLibType; buflen = strlen(fontLib->name); if ((buf = PM_malloc(buflen + 1)) == NULL) FATALERROR(grNoMem); strcpy(buf, fontLib->name); entry->isBold = entry->isItalic = false; do { foundSuffix = false; if (buflen >= 5 && strcmp(buf + buflen - 5, " Bold") == 0) { foundSuffix = true; entry->isBold = true; buf[buflen - 5] = '\0'; buflen -= 5; } if (buflen >= 7 && strcmp(buf + buflen - 7, " Italic") == 0) { foundSuffix = true; entry->isItalic = true; buf[buflen - 7] = '\0'; buflen -= 7; } } while (buflen > 0 && foundSuffix); if (buflen == 0) { if ((entry->familyName = PM_malloc(strlen(filename) + 1)) == NULL) FATALERROR(grNoMem); strcpy(entry->familyName, filename); } else { if ((entry->familyName = PM_malloc(strlen(buf) + 1)) == NULL) FATALERROR(grNoMem); strcpy(entry->familyName, buf); } PM_free(buf); /* Check if the font is fixed width or proportional. In absence of better method, we do it by comparing average and maximum character width: */ entry->isFixed = fontIsFixed(fontLib); MGL_closeFontLib(fontLib); cache->validCnt++; entry->exists = true; }
/**************************************************************************** DESCRIPTION: Locates the specified bitmap file and loads it into a device context. HEADER: mgraph.h PARAMETERS: dc - Device context to load bitmap into f - Pointer to opened bitmap file dwSize - Size of the bitmap file dwOffset - Offset into the file dstLeft - Left coordinate to place bitmap at dstTop - Top coordinate to place bitmap at loadPalette - Should we load the palette values as well? RETURNS: True if the bitmap was successfully loaded. REMARKS: This function is the same as MGL_loadBitmapIntoDC, however it works with a previously opened file. This allows you to create your own large files with multiple files embedded in them. SEE ALSO: MGL_loadBitmapIntoDC ****************************************************************************/ ibool MGLAPI MGL_loadBitmapIntoDCExt( MGLDC *dc, FILE *f, ulong dwOffset, ulong dwSize, int dstLeft, int dstTop, ibool loadPalette) { bitmap_t bmh; palette_t pal[256]; /* Temporary space for palette */ pixel_format_t pf; int i,palSize,height; ibool oldCheckId,isRLE; /* Read bitmap header */ if (!readBitmapHeaderExt(&bmh,pal,&palSize,&pf,f,dwOffset,loadPalette,&isRLE)) return false; /* Allocate a temporary bitmap to convert the scanlines */ bmh.pal = pal; bmh.pf = &pf; if ((bmh.surface = PM_malloc(bmh.bytesPerLine)) == NULL) { FATALERROR(grNoMem); return false; } oldCheckId = MGL_checkIdentityPalette(false); /* Store the palette in the destination DC */ if (loadPalette && (bmh.bitsPerPixel == 4 || bmh.bitsPerPixel == 8)) { MGL_setPalette(dc,pal,palSize / sizeof(palette_t),0); if (MGL_getVisualPage(dc) == MGL_getActivePage(dc)) MGL_realizePalette(dc,palSize / sizeof(palette_t),0,false); } else if (loadPalette && ((dc->mi.modeFlags & MGL_IS_COLOR_INDEX) && bmh.bitsPerPixel > 8)) { MGL_getHalfTonePalette(pal); MGL_setPalette(dc,pal,MGL_getPaletteSize(dc),0); if (MGL_getVisualPage(dc) == MGL_getActivePage(dc)) MGL_realizePalette(dc,MGL_getPaletteSize(dc),0,false); } /* Now read in the bits in the bitmap, by reading the data a scanline * at a time into our temporary memory DC, and then blting this to * the destination DC. We need to handle both cases of bottom up and * top down DIB's, plus RLE decoding. */ height = bmh.height; if (isRLE) { /* Decode RLE bottom up DIB via MGL scratch buffer */ bufStart = (uchar*)_MGL_buf; bufSize = _MGL_bufSize; readChunk(f); gcount = gdata = 0; bmh.height = 1; for (i = height-1; i >= 0; i--) { decodeScan(f,bmh.surface,bmh.bytesPerLine); MGL_putBitmap(dc,dstLeft,dstTop+i,&bmh,MGL_REPLACE_MODE); } } else if (height < 0) { /* Top down DIB */ height = -bmh.height; bmh.height = 1; for (i = 0; i < height; i++) { __MGL_fread(bmh.surface,1,bmh.bytesPerLine,f); MGL_putBitmap(dc,dstLeft,dstTop+i,&bmh,MGL_REPLACE_MODE); } } else { /* Bottom up DIB */ bmh.height = 1; for (i = height-1; i >= 0; i--) { __MGL_fread(bmh.surface,1,bmh.bytesPerLine,f); MGL_putBitmap(dc,dstLeft,dstTop+i,&bmh,MGL_REPLACE_MODE); } } PM_free(bmh.surface); MGL_checkIdentityPalette(oldCheckId); (void)dwSize; return true; }
static void InitPMCode(void) /**************************************************************************** * * Function: InitPMCode - 32 bit protected mode version * * Description: Finds the address of and relocates the protected mode * code block from the VBE 2.0 into a local memory block. The * memory block is allocated with malloc() and must be freed * with VBE_freePMCode() after graphics processing is complete. * * Note that this buffer _must_ be recopied after each mode set, * as the routines will change depending on the underlying * video mode. * ****************************************************************************/ { RMREGS regs; RMSREGS sregs; uchar *code; int pmLen; if (!state->pmInfo && state->VBEVersion >= 0x200) { regs.x.ax = 0x4F0A; regs.x.bx = 0; PM_int86x(0x10,®s,®s,&sregs); if (regs.x.ax != VBE_SUCCESS) return; if (VBE_shared) state->pmInfo = PM_mallocShared(regs.x.cx); else state->pmInfo = PM_malloc(regs.x.cx); if (state->pmInfo == NULL) return; state->pmInfo32 = state->pmInfo; pmLen = regs.x.cx; /* Relocate the block into our local data segment */ code = PM_mapRealPointer(sregs.es,regs.x.di); memcpy(state->pmInfo,code,pmLen); /* Now do a sanity check on the information we recieve to ensure * that is is correct. Some BIOS return totally bogus information * in here (Matrox is one)! Under DOS this works OK, but under OS/2 * we are screwed. */ if (state->pmInfo->setWindow >= pmLen || state->pmInfo->setDisplayStart >= pmLen || state->pmInfo->setPalette >= pmLen || state->pmInfo->IOPrivInfo >= pmLen) { if (VBE_shared) PM_freeShared(state->pmInfo); else PM_free(state->pmInfo); state->pmInfo32 = state->pmInfo = NULL; return; } /* Read the IO priveledge info and determine if we need to * pass a selector to MMIO registers to the bank switch code. * Since we no longer support selector allocation, we no longer * support this mechanism so we disable the protected mode * interface in this case. */ if (state->pmInfo->IOPrivInfo && !state->MMIOSel) { ushort *p = (ushort*)((uchar*)state->pmInfo + state->pmInfo->IOPrivInfo); while (*p != 0xFFFF) p++; p++; if (*p != 0xFFFF) VBE_freePMCode(); } } }
/**************************************************************************** REMARKS: VDD implementation of the ANSI C fopen function. ****************************************************************************/ FILE * fopen( const char *filename, const char *mode) { FILE *f = PM_malloc(sizeof(FILE)); long oldpos; ULONG rc, ulAction; ULONG omode, oflags; if (f != NULL) { f->offset = 0; f->text = (mode[1] == 't' || mode[2] == 't'); f->writemode = (mode[0] == 'w') || (mode[0] == 'a'); f->unputc = EOF; f->endp = f->buf + sizeof(f->buf); f->curp = f->startp = f->buf; if (mode[0] == 'r') { #ifdef __OS2_VDD__ omode = VDHOPEN_ACCESS_READONLY | VDHOPEN_SHARE_DENYNONE; oflags = VDHOPEN_ACTION_OPEN_IF_EXISTS | VDHOPEN_ACTION_FAIL_IF_NEW; #else omode = OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE; oflags = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW; #endif } else if (mode[0] == 'w') { #ifdef __OS2_VDD__ omode = VDHOPEN_ACCESS_WRITEONLY | VDHOPEN_SHARE_DENYWRITE; oflags = VDHOPEN_ACTION_REPLACE_IF_EXISTS | VDHOPEN_ACTION_CREATE_IF_NEW; #else omode = OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYWRITE; oflags = OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW; #endif } else { #ifdef __OS2_VDD__ omode = VDHOPEN_ACCESS_READWRITE | VDHOPEN_SHARE_DENYWRITE; oflags = VDHOPEN_ACTION_OPEN_IF_EXISTS | VDHOPEN_ACTION_CREATE_IF_NEW; #else omode = OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYWRITE; oflags = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW; #endif } rc = _OS2Open((PSZ)filename, (PHFILE)&f->handle, &ulAction, 0, VDHOPEN_FILE_NORMAL, oflags, omode, NULL); if (rc != 0) { PM_free(f); return NULL; } #ifdef __OS2_VDD__ f->filesize = VDHSeek((HFILE)f->handle, 0, VDHSK_END_OF_FILE); #else rc = DosSetFilePtr((HFILE)f->handle, 0, FILE_END, &f->filesize); #endif if (mode[0] == 'a') fseek(f,0,2); } return f; }