/* * Adds a destructor to a block. */ dip_status VMAddDtor( imp_image_handle *ii, virt_mem start, void ( *dtor )( imp_image_handle *ii, void *user ), void *user ) { unsigned dir_idx; unsigned pg_idx; virt_page *pg; /* locate the block. */ dir_idx = GET_DIR( start ); if( ii->virt[dir_idx] != NULL ) { pg_idx = GET_PAGE( start ); pg = ii->virt[dir_idx][pg_idx]; if( pg != NULL ) { /* create a new dtor node and link it in */ vm_dtor *node = DCAlloc( sizeof( *node ) ); if( node != NULL ) { node->user = user; node->dtor = dtor; node->next = pg->block->first_dtor; pg->block->first_dtor = node; return( DS_OK ); } return( DS_ERR | DS_NO_MEM ); } } return( DS_ERR | DS_FAIL ); }
const critbit__extnode_t *critbit__lookup(const critbit__node_t *n, const void *key, size_t keylen) { const unsigned char *ukey = key; const unsigned char *ukeyend = ukey + keylen; int dir; for (; IS_INTERNAL(n); n = n->child[dir]) dir = GET_DIR(ukey, ukeyend, n->byte, n->otherbits); return FROM_STORE(n); }
DWORD WINAPI GetK32ProcAddress(int ord) { static HANDLE hmod = 0; IMAGE_NT_HEADERS *hdr; IMAGE_EXPORT_DIRECTORY *exp; DWORD *AddrFunc; WORD enewhdr, *pw; int did_load = 0, i; BYTE *moddb; if (hmod == 0) // one-time static init hmod = GetModuleHandle("KERNEL32"); if (hmod == 0) // still return 0; moddb = (BYTE *) hmod; pw = (WORD *) &moddb[0]; if (*pw != EMAGIC) return 0; pw = (WORD *) &moddb[ENEWHDR]; enewhdr = *pw; pw = (WORD *) &moddb[enewhdr]; if (*pw != PEMAGIC) return 0; hdr = (IMAGE_NT_HEADERS *) pw; // Note: offset from moddb, *NOT* from hdr! exp = (IMAGE_EXPORT_DIRECTORY *) (((DWORD) moddb) + ((DWORD) GET_DIR(IMAGE_DIRECTORY_ENTRY_EXPORT))); AddrFunc = (DWORD *) (moddb + (DWORD) exp->AddressOfFunctions); // should verify that e.g.: // GetProcAddress(hmod, "VirtualAlloc") == GetK32ProcAddress(710); ord--; // table is 0-based, ordinals are 1-based if (ord < exp->NumberOfFunctions) return ((DWORD) (moddb + AddrFunc[ord])); else return 0; }
void *VMBlock( imp_image_handle *iih, virt_mem start, size_t len ) { unsigned dir_idx; unsigned pg_idx; unsigned tmp_idx; unsigned i; unsigned j; unsigned num_pages; virt_mem pg_start; virt_page *pg; virt_page *zero; loaded_block *block; dir_idx = GET_DIR( start ); if( iih->virt[dir_idx] == NULL ) { if( !InitPageDir( iih, dir_idx ) ) { return( NULL ); } } pg_idx = GET_PAGE( start ); len += start % VM_PAGE_SIZE; pg_start = start & ~(virt_mem)(VM_PAGE_SIZE - 1); pg = iih->virt[dir_idx][pg_idx]; if( pg == NULL || ( pg->block->len - pg->offset ) < len ) { /* unloaded previously loaded block */ if( pg != NULL ) { tmp_idx = dir_idx; /* find first page of the block */ i = pg_idx; for( ;; ) { iih->virt[tmp_idx][i] = NULL; if( pg->offset == 0 ) break; if( i == 0 ) { --tmp_idx; i = DIR_SIZE; } --i; --pg; } DCFree( pg ); } num_pages = BLOCK_FACTOR( len, VM_PAGE_SIZE ); pg = DCAlloc( num_pages * ( sizeof( *pg ) + VM_PAGE_SIZE ) + sizeof( loaded_block ) - 1 ); if( pg == NULL ) { DCStatus( DS_ERR | DS_NO_MEM ); return( NULL ); } /* set up new page table entries */ block = (loaded_block *)&pg[num_pages]; tmp_idx = dir_idx; for( j = pg_idx, i = 0; i < num_pages; ++j, ++i ) { pg[i].block = block; pg[i].offset = i * VM_PAGE_SIZE; if( j >= DIR_SIZE ) { ++tmp_idx; j = 0; } if( iih->virt[tmp_idx] == NULL ) { if( !InitPageDir( iih, tmp_idx ) ) { /* unwind the setup already done */ num_pages = i; for( i = 0; i < num_pages; ++i, ++pg_idx ) { if( pg_idx >= DIR_SIZE ) { ++dir_idx; pg_idx = 0; } iih->virt[dir_idx][pg_idx] = NULL; } DCFree( pg ); return( NULL ); } } if( iih->virt[tmp_idx][j] != NULL ) { /* We just ran into another allocated block, so we have to kill all the pages mapped in by it. We know that if the page pointer is non-NULL, it will be offset==0 since KillPages will clean out the others. */ KillPages( iih, tmp_idx, j ); } iih->virt[tmp_idx][j] = &pg[i]; } /* read in new block */ len = num_pages * VM_PAGE_SIZE; block->len = len; pg_start += iih->bias; if( DCSeek( iih->sym_fp, pg_start, DIG_ORG ) ) { DCStatus( DS_ERR | DS_FSEEK_FAILED ); return( NULL ); } /* last block might be a short read */ if( DCRead( iih->sym_fp, pg->block->data, len ) == DIG_RW_ERROR ) { DCStatus( DS_ERR | DS_FREAD_FAILED ); return( NULL ); } pg = iih->virt[dir_idx][pg_idx]; } ++TimeStamp; if( TimeStamp == 0 ) { /* deal with wrap-around */ for( iih = ImageList; iih != NULL; iih = iih->next_image ) { if( iih->virt != NULL ) { for( i = iih->vm_dir_num; i-- > 0; ) { if( iih->virt[i] != NULL ) { for( j = DIR_SIZE; j-- > 0; ) { zero = iih->virt[i][j]; if( zero != NULL ) { zero->block->time_stamp = 0; } } } } } } ++TimeStamp; } pg->block->time_stamp = TimeStamp; return( &pg->block->data[(start & (VM_PAGE_SIZE - 1)) + pg->offset] ); }