📄 nt_printing.c
字号:
return 0; } *list = tl; (*list)[n] = form; n++; } return n;}/****************************************************************************write a form struct list****************************************************************************/int write_ntforms(nt_forms_struct **list, int number){ pstring buf, key; int len; TDB_DATA kbuf,dbuf; int i; for (i=0;i<number;i++) { /* save index, so list is rebuilt in correct order */ len = tdb_pack(buf, sizeof(buf), "dddddddd", i, (*list)[i].flag, (*list)[i].width, (*list)[i].length, (*list)[i].left, (*list)[i].top, (*list)[i].right, (*list)[i].bottom); if (len > sizeof(buf)) break; slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name); kbuf.dsize = strlen(key)+1; kbuf.dptr = key; dbuf.dsize = len; dbuf.dptr = buf; if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break; } return i;}/****************************************************************************add a form struct at the end of the list****************************************************************************/BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count){ int n=0; BOOL update; fstring form_name; nt_forms_struct *tl; /* * NT tries to add forms even when * they are already in the base * only update the values if already present */ update=False; unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1); for (n=0; n<*count; n++) { if ( strequal((*list)[n].name, form_name) ) { update=True; break; } } if (update==False) { if((tl=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) { DEBUG(0,("add_a_form: failed to enlarge forms list!\n")); return False; } *list = tl; unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1); (*count)++; } (*list)[n].flag=form->flags; (*list)[n].width=form->size_x; (*list)[n].length=form->size_y; (*list)[n].left=form->left; (*list)[n].top=form->top; (*list)[n].right=form->right; (*list)[n].bottom=form->bottom; DEBUG(6,("add_a_form: Successfully %s form [%s]\n", update ? "updated" : "added", form_name)); return True;}/**************************************************************************** Delete a named form struct.****************************************************************************/BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret){ pstring key; TDB_DATA kbuf; int n=0; fstring form_name; *ret = WERR_OK; unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1); for (n=0; n<*count; n++) { if (!strncmp((*list)[n].name, form_name, strlen(form_name))) { DEBUG(103, ("delete_a_form, [%s] in list\n", form_name)); break; } } if (n == *count) { DEBUG(10,("delete_a_form, [%s] not found\n", form_name)); *ret = WERR_INVALID_PARAM; return False; } slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name); kbuf.dsize = strlen(key)+1; kbuf.dptr = key; if (tdb_delete(tdb_forms, kbuf) != 0) { *ret = WERR_NOMEM; return False; } return True;}/**************************************************************************** Update a form struct.****************************************************************************/void update_a_form(nt_forms_struct **list, const FORM *form, int count){ int n=0; fstring form_name; unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1); DEBUG(106, ("[%s]\n", form_name)); for (n=0; n<count; n++) { DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name)); if (!strncmp((*list)[n].name, form_name, strlen(form_name))) break; } if (n==count) return; (*list)[n].flag=form->flags; (*list)[n].width=form->size_x; (*list)[n].length=form->size_y; (*list)[n].left=form->left; (*list)[n].top=form->top; (*list)[n].right=form->right; (*list)[n].bottom=form->bottom;}/**************************************************************************** Get the nt drivers list. Traverse the database and look-up the matching names.****************************************************************************/int get_ntdrivers(fstring **list, const char *architecture, uint32 version){ int total=0; const char *short_archi; fstring *fl; pstring key; TDB_DATA kbuf, newkey; short_archi = get_short_archi(architecture); slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version); for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr; newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) { if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue; if((fl = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) { DEBUG(0,("get_ntdrivers: failed to enlarge list!\n")); return -1; } else *list = fl; fstrcpy((*list)[total], kbuf.dptr+strlen(key)); total++; } return(total);}/****************************************************************************function to do the mapping between the long architecture name andthe short one.****************************************************************************/const char *get_short_archi(const char *long_archi){ int i=-1; DEBUG(107,("Getting architecture dependant directory\n")); do { i++; } while ( (archi_table[i].long_archi!=NULL ) && StrCaseCmp(long_archi, archi_table[i].long_archi) ); if (archi_table[i].long_archi==NULL) { DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi)); return NULL; } /* this might be client code - but shouldn't this be an fstrcpy etc? */ DEBUGADD(108,("index: [%d]\n", i)); DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi)); DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi)); return archi_table[i].short_archi;}/**************************************************************************** Version information in Microsoft files is held in a VS_VERSION_INFO structure. There are two case to be covered here: PE (Portable Executable) and NE (New Executable) files. Both files support the same INFO structure, but PE files store the signature in unicode, and NE files store it as !unicode. returns -1 on error, 1 on version info found, and 0 on no version info found.****************************************************************************/static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor){ int i; char *buf = NULL; ssize_t byte_count; if ((buf=SMB_MALLOC(PE_HEADER_SIZE)) == NULL) { DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n", fname, PE_HEADER_SIZE)); goto error_exit; } /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */ if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) { DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n", fname, (unsigned long)byte_count)); goto no_version_info; } /* Is this really a DOS header? */ if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) { DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n", fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET))); goto no_version_info; } /* Skip OEM header (if any) and the DOS stub to start of Windows header */ if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) { DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n", fname, errno)); /* Assume this isn't an error... the file just looks sort of like a PE/NE file */ goto no_version_info; } if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) { DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n", fname, (unsigned long)byte_count)); /* Assume this isn't an error... the file just looks sort of like a PE/NE file */ goto no_version_info; } /* The header may be a PE (Portable Executable) or an NE (New Executable) */ if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) { unsigned int num_sections; unsigned int section_table_bytes; if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) { DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n", fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET))); /* At this point, we assume the file is in error. It still could be somthing * else besides a PE file, but it unlikely at this point. */ goto error_exit; } /* get the section table */ num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS); section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE; if (section_table_bytes == 0) goto error_exit; SAFE_FREE(buf); if ((buf=SMB_MALLOC(section_table_bytes)) == NULL) { DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n", fname, section_table_bytes)); goto error_exit; } if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) { DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n", fname, (unsigned long)byte_count)); goto error_exit; } /* Iterate the section table looking for the resource section ".rsrc" */ for (i = 0; i < num_sections; i++) { int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE; if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) { unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET); unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET); if (section_bytes == 0) goto error_exit; SAFE_FREE(buf); if ((buf=SMB_MALLOC(section_bytes)) == NULL) { DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n", fname, section_bytes)); goto error_exit; } /* Seek to the start of the .rsrc section info */ if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) { DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n", fname, errno)); goto error_exit; } if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) { DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n", fname, (unsigned long)byte_count)); goto error_exit; } if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE) goto error_exit; for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) { /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */ if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') { /* Align to next long address */ int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc; if (IVAL(buf,pos) == VS_MAGIC_VALUE) { *major = IVAL(buf,pos+VS_MAJOR_OFFSET); *minor = IVAL(buf,pos+VS_MINOR_OFFSET); DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n", fname, *major, *minor, (*major>>16)&0xffff, *major&0xffff, (*minor>>16)&0xffff, *minor&0xffff)); SAFE_FREE(buf); return 1; } } } } } /* Version info not found, fall back to origin date/time */ DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname)); SAFE_FREE(buf); return 0; } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) { if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) { DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n", fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET))); /* At this point, we assume the file is in error. It still could be somthing * else besides a NE file, but it unlikely at this point. */ goto error_exit; } /* Allocate a bit more space to speed up things */ SAFE_FREE(buf); if ((buf=SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) { DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n", fname, PE_HEADER_SIZE)); goto error_exit; } /* This is a HACK! I got tired of trying to sort through the messy * 'NE' file format. If anyone wants to clean this up please have at * it, but this works. 'NE' files will eventually fade away. JRR */ while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) { /* Cover case that should not occur in a well formed 'NE' .dll file */ if (byte_count-VS_VERSION_INFO_SIZE <= 0) break; for(i=0; i<byte_count; i++) { /* Fast skip past data that can't possibly match */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -