Esempio n. 1
0
/**
 * @brief Inserts an item to a double linked list.
 * @details Allocates memory for the item to be inserted.
 * @param[in,out] phead pointer to a variable pointing to the list head.
 * @param[in] prev pointer to an item preceeding to the new item.
 * If this parameter is NULL, the new head will be inserted.
 * @param[in] size the size of the item to be inserted, in bytes.
 * @return Pointer to the inserted list item. In case of allocation failure
 * this routine calls the killer registered by winx_set_killer and returns NULL then.
 */
list_entry *winx_list_insert(list_entry **phead,list_entry *prev,long size)
{
    list_entry *new_item;
    
    /*
    * Avoid winx_dbg_xxx calls here
    * to avoid recursion.
    */

    if(size < sizeof(list_entry))
        return NULL;

    new_item = (list_entry *)winx_malloc(size);

    /* is list empty? */
    if(*phead == NULL){
        *phead = new_item;
        new_item->prev = new_item->next = new_item;
        return new_item;
    }

    /* insert as the new head? */
    if(prev == NULL){
        prev = (*phead)->prev;
        *phead = new_item;
    }

    /* insert after the item specified by prev argument */
    new_item->prev = prev;
    new_item->next = prev->next;
    new_item->prev->next = new_item;
    new_item->next->prev = new_item;
    return new_item;
}
Esempio n. 2
0
/**
 * @internal
 * @brief Saves the list of boot
 * execute programs to registry.
 * @return Zero for success,
 * negative value otherwise.
 */
static int save_boot_exec_list(struct cmd *list)
{
    struct cmd *c;
    int length = 1;
    wchar_t *commands, *p;
    NTSTATUS status;
    
    for(c = list; c; c = c->next){
        if(c->cmd[0]) length += (int)wcslen(c->cmd) + 1;
        if(c->next == list) break;
    }
    commands = winx_malloc(length * sizeof(wchar_t));
    memset(commands,0,length * sizeof(wchar_t));
    for(c = list, p = commands; c; c = c->next){
        if(c->cmd[0]){
            wcscpy(p,c->cmd);
            p += wcslen(c->cmd) + 1;
        }
        if(c->next == list) break;
    }
    
    status = RtlWriteRegistryValue(RTL_REGISTRY_CONTROL,
        L"Session Manager",L"BootExecute",REG_MULTI_SZ,
        commands,length * sizeof(wchar_t));
    winx_free(commands);
    if(!NT_SUCCESS(status)){
        strace(status,"cannot save list of boot execute commands");
        return (-1);
    }
    return 0;
}
Esempio n. 3
0
/**
 * @brief Queries an environment variable.
 * @param[in] name the environment variable name.
 * @return The value of the environment variable.
 * NULL indicates failure.
 * @note The returned string should be freed
 * by the winx_free call after its use.
 */
wchar_t *winx_getenv(wchar_t *name)
{
    wchar_t *value;
    UNICODE_STRING n, v;
    NTSTATUS status;
    
    DbgCheck1(name,NULL);
    
    value = winx_malloc(MAX_ENV_VALUE_LENGTH * sizeof(wchar_t));

    RtlInitUnicodeString(&n,name);
    v.Buffer = value;
    v.Length = 0;
    v.MaximumLength = MAX_ENV_VALUE_LENGTH * sizeof(wchar_t);
    status = RtlQueryEnvironmentVariable_U(NULL,&n,&v);
    if(!NT_SUCCESS(status)){
        strace(status,"cannot query %ws",name);
        winx_free(value);
        return NULL;
    }
    if(value[0] == 0){
        winx_free(value);
        return NULL;
    }
    return value;
}
Esempio n. 4
0
/**
 * @internal
 * @brief Retrieves the volume label.
 * @param[in] hRoot handle to the
 * root directory.
 * @param[out] pointer to the structure
 * receiving the volume label.
 */
static void get_volume_label(HANDLE hRoot,winx_volume_information *v)
{
    FILE_FS_VOLUME_INFORMATION *ffvi;
    int buffer_size;
    IO_STATUS_BLOCK IoStatusBlock;
    NTSTATUS status;
    
    /* reset label */
    v->label[0] = 0;
    
    /* allocate memory */
    buffer_size = (sizeof(FILE_FS_VOLUME_INFORMATION) - sizeof(wchar_t)) + (MAX_PATH + 1) * sizeof(wchar_t);
    ffvi = winx_malloc(buffer_size);
    
    /* try to get actual label */
    RtlZeroMemory(ffvi,buffer_size);
    status = NtQueryVolumeInformationFile(hRoot,&IoStatusBlock,ffvi,
                buffer_size,FileFsVolumeInformation);
    if(!NT_SUCCESS(status)){
        strace(status,"cannot get volume label of drive %c:",
            v->volume_letter);
        winx_free(ffvi);
        return;
    }
    wcsncpy(v->label,ffvi->VolumeLabel,MAX_PATH);
    v->label[MAX_PATH] = 0;
    winx_free(ffvi);
}
Esempio n. 5
0
/**
 * @brief Adds a file block to
 * the binary tree of all file blocks.
 * @return Zero for success, 
 * negative value otherwise.
 * @note Destroys the tree in case of errors.
 */
int add_block_to_file_blocks_tree(udefrag_job_parameters *jp, winx_file_info *file, winx_blockmap *block)
{
    struct file_block *fb;
    void **p;
    
    if(file == NULL || block == NULL)
        return (-1);
    
    if(jp->file_blocks == NULL)
        return (-1);

    fb = winx_malloc(sizeof *fb);
    fb->file = file;
    fb->block = block;
    p = prb_probe(jp->file_blocks,(void *)fb);
    /* if a duplicate item exists... */
    if(*p != fb){
        etrace("a duplicate found");
        winx_free(fb);
    }
    return 0;
}
Esempio n. 6
0
/**
 * @internal
 * @brief Retrieves the name of the file system.
 * @param[in] hRoot handle to the root directory.
 * @param[out] pointer to the structure receiving
 * the filesystem name.
 * @return Zero for success, negative value otherwise.
 * @note We could analyze the first sector of the 
 * partition directly, but this method is not so swift
 * as it accesses the disk physically.
 */
static int get_filesystem_name(HANDLE hRoot,winx_volume_information *v)
{
    FILE_FS_ATTRIBUTE_INFORMATION *pfa;
    int fs_attr_info_size;
    IO_STATUS_BLOCK IoStatusBlock;
    NTSTATUS status;
    wchar_t fs_name[MAX_FS_NAME_LENGTH + 1];
    int length;

    fs_attr_info_size = MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
    pfa = winx_malloc(fs_attr_info_size);
    
    RtlZeroMemory(pfa,fs_attr_info_size);
    status = NtQueryVolumeInformationFile(hRoot,&IoStatusBlock,pfa,
                fs_attr_info_size,FileFsAttributeInformation);
    if(!NT_SUCCESS(status)){
        strace(status,"cannot get file system name of drive %c:",v->volume_letter);
        winx_free(pfa);
        return (-1);
    }
    
    /*
    * pfa->FileSystemName.Buffer may be not NULL terminated
    * (theoretically), so name extraction is more tricky
    * than it should be.
    */
    length = min(MAX_FS_NAME_LENGTH,pfa->FileSystemNameLength / sizeof(wchar_t));
    wcsncpy(fs_name,pfa->FileSystemName,length);
    fs_name[length] = 0;
    _snprintf(v->fs_name,MAX_FS_NAME_LENGTH,"%ws",fs_name);
    v->fs_name[MAX_FS_NAME_LENGTH] = 0;

    /* cleanup */
    winx_free(pfa);
    return 0;
}
Esempio n. 7
0
/**
 * @brief Retrieves the list of free regions on the volume.
 * @param[in] volume_letter the volume letter.
 * @param[in] flags the combination of WINX_GVR_xxx flags.
 * @param[in] cb the address of the procedure to be called
 * each time when the free region is found on the volume.
 * If the callback procedure returns nonzero value,
 * the scan terminates immediately.
 * @param[in] user_defined_data pointer to the data
 * passed to the registered callback.
 * @return List of the free regions, NULL indicates that
 * either disk is full (unlikely) or some error occured.
 * @note
 * - It is possible to scan disk partially by
 * requesting the scan termination through the callback
 * procedure.
 * - The callback procedure should complete as quickly
 * as possible to avoid slowdown of the scan.
 */
winx_volume_region *winx_get_free_volume_regions(char volume_letter,
        int flags, volume_region_callback cb, void *user_defined_data)
{
    winx_volume_region *rlist = NULL, *rgn = NULL;
    BITMAP_DESCRIPTOR *bitmap;
    #define LLINVALID   ((ULONGLONG) -1)
    #define BITMAPBYTES 4096
    #define BITMAPSIZE  (BITMAPBYTES + 2 * sizeof(ULONGLONG))
    /* bit shifting array for efficient processing of the bitmap */
    unsigned char bitshift[] = { 1, 2, 4, 8, 16, 32, 64, 128 };
    WINX_FILE *f;
    ULONGLONG i, start, next, free_rgn_start;
    IO_STATUS_BLOCK iosb;
    NTSTATUS status;
    
    /* ensure that it will work on w2k */
    volume_letter = winx_toupper(volume_letter);
    
    /* allocate memory */
    bitmap = winx_malloc(BITMAPSIZE);
    
    /* open volume */
    f = winx_vopen(volume_letter);
    if(f == NULL){
        winx_free(bitmap);
        return NULL;
    }
    
    /* get volume bitmap */
    next = 0, free_rgn_start = LLINVALID;
    do {
        /* get next portion of the bitmap */
        memset(bitmap,0,BITMAPSIZE);
        status = NtFsControlFile(winx_fileno(f),NULL,NULL,0,&iosb,
            FSCTL_GET_VOLUME_BITMAP,&next,sizeof(ULONGLONG),
            bitmap,BITMAPSIZE);
        if(NT_SUCCESS(status)){
            NtWaitForSingleObject(winx_fileno(f),FALSE,NULL);
            status = iosb.Status;
        }
        if(status != STATUS_SUCCESS && status != STATUS_BUFFER_OVERFLOW){
            strace(status,"cannot get volume bitmap");
            winx_fclose(f);
            winx_free(bitmap);
            if(flags & WINX_GVR_ALLOW_PARTIAL_SCAN){
                return rlist;
            } else {
                winx_list_destroy((list_entry **)(void *)&rlist);
                return NULL;
            }
        }
        
        /* scan through the returned bitmap info */
        start = bitmap->StartLcn;
        for(i = 0; i < min(bitmap->ClustersToEndOfVol, 8 * BITMAPBYTES); i++){
            if(!(bitmap->Map[ i/8 ] & bitshift[ i % 8 ])){
                /* cluster is free */
                if(free_rgn_start == LLINVALID)
                    free_rgn_start = start + i;
            } else {
                /* cluster isn't free */
                if(free_rgn_start != LLINVALID){
                    /* add free region to the list */
                    rgn = (winx_volume_region *)winx_list_insert((list_entry **)(void *)&rlist,
                        (list_entry *)rgn,sizeof(winx_volume_region));
                    rgn->lcn = free_rgn_start;
                    rgn->length = start + i - free_rgn_start;
                    if(cb != NULL){
                        if(cb(rgn,user_defined_data))
                            goto done;
                    }
                    free_rgn_start = LLINVALID;
                }
            }
        }
        
        /* go to the next portion of data */
        next = bitmap->StartLcn + i;
    } while(status != STATUS_SUCCESS);

    if(free_rgn_start != LLINVALID){
        /* add free region to the list */
        rgn = (winx_volume_region *)winx_list_insert((list_entry **)(void *)&rlist,
            (list_entry *)rgn,sizeof(winx_volume_region));
        rgn->lcn = free_rgn_start;
        rgn->length = start + i - free_rgn_start;
        if(cb != NULL){
            if(cb(rgn,user_defined_data))
                goto done;
        }
        free_rgn_start = LLINVALID;
    }

done:    
    /* cleanup */
    winx_fclose(f);
    winx_free(bitmap);
    return rlist;
}