How the application works, recovered only from the compiled binaries in its release folder. The source code, design documents and developers were not consulted.
github.com/alexeyban/tsd · SmartDeviceProject3/SmartDeviceProject2/SmartDeviceProject2/bin/Release · 31 files · 12 managed assemblies · compiled by EKOS 2026-09-18 · extractor ekos-cil-metadata/v2 · zero LLM calls
TSD (the handheld window is titled “Data Collection Terminal”) is a two-part retail back-office system. Store staff use a Windows CE handheld to scan goods for price checks, stock-taking, receiving trucks and boxes, and returns. A desktop exchange server loads reference data onto the handheld and pulls the scan results back.
FamilTsdDB) and copies that database to the terminal. compiledscannedbarcodes.txt and register.txt the moment it happens. The files are copied back to the desktop and archived with a timestamp, and each import's status is emailed. compiled observedNavCode, and the handheld shows it under the label “Navision code”. The upstream ERP is therefore most likely Microsoft Dynamics NAV. readingEvery statement is tagged with how EKOS obtained it. Most statements also carry a binary · token locator: an ECMA-335 metadata token such as TSDClient.exe · 0x0600004B. That token names the exact method in the exact build (binary SHA-256 is recorded on every fact). Any claim can be re-checked with ekos_binary_explain or ekos query object.
ekos_impact, ekos_dependents, ekos_neighborhood)
reading an interpretation that joins several EKOS facts. It is not itself a compiled fact, and the evidence it rests on is stated.
The application's user interface is in Russian. Every on-screen string quoted here is an English translation of a constant compiled into the binaries; the Russian originals can be read with ekos_binary_explain. File names containing the Russian word for “copy” are shown translated.
EKOS detects formats by magic bytes and the PE CLI header, never by file extension. Of the 14 PE files, 13 are managed .NET assemblies and one (MCSSLib.dll, ARM Thumb, Windows CE) is native code. EKOS records the native file as a File and reads nothing from it. compiled
| Assembly | File | Role | Types | Methods | CLR | Used by |
|---|---|---|---|---|---|---|
| TSDClient | TSDClient.exe | Handheld application, window title “Data Collection Terminal” | 117 | 1,189 | v2.0 | entry point |
| TSDClient | TSDClient - Copy.exe | Second copy of the handheld app, a different build (two fewer types) | 115 | 1,155 | v2.0 | — |
| TSDServer | TSDServer.exe | Desktop exchange server, window title “TSD Exchange Server” | 59 | 817 | v2.0 | entry point |
| OBReadLibNet | obreadlibnet.dll | Optical barcode reader SDK wrapper (namespace Calib) | 7 | 209 | v1.1 | TSDClient ×2 graph |
| BluetoothLibNet | bluetoothlibnet.dll | Bluetooth stack SDK wrapper (Calib) | 8 | 125 | v1.1 | TSDClient ×2 graph |
| SystemLibnet | systemlibnet.dll | Device system SDK: buzzer, vibrator, events (Calib) | 5 | 246 | v1.1 | TSDClient ×2 graph |
| ImagerLibNet | ImagerLibNet.dll | Camera imager / OCR SDK (Calib) | 13 | 244 | v1.1 | nothing graph |
| MoFlinkLibNet | MoFlinkLibNet.dll | Device SDK: FLK_* file, status and system-info structures (Calib) | 18 | 217 | v1.1 | nothing graph |
| OpenNETCF | OpenNETCF.dll | OpenNETCF Smart Device Framework (third party) | 375 | 2,591 | v2.0 | OpenNETCF.Drawing, .Windows.Forms |
| OpenNETCF.Windows.Forms | OpenNETCF.Windows.Forms.dll | OpenNETCF UI controls | 132 | 1,248 | v2.0 | TSDClient ×2 |
| OpenNETCF.Drawing | OpenNETCF.Drawing.dll | OpenNETCF drawing | 30 | 197 | v2.0 | OpenNETCF.Windows.Forms |
| ControlsLib | controlslib.dll | Custom controls, namespace Bananamama.BackOffice.TSD.Client | 9 | 89 | v2.0 | nothing graph |
The CLR column is the metadata version string: v2.0.50727 is .NET Compact Framework 2.0, and v1.1.4322 is the device vendor's older SDK build. "Used by" counts real DependsOn edges resolved onto binaries in this same folder. compiled graph
The Calib namespace, the OBR*/BT*/Sys* API names, and a test-print string naming "CASIO IT-600 or DT-X11" (in BTPrintClass) together suggest the handheld hardware is a Casio industrial terminal. reading
Two executables and a set of device SDK wrappers. The only channel between desktop and handheld is file copy over ActiveSync, through OpenNETCF.Desktop.Communication.RAPI. compiled
The handheld app declares its classes in the TSDServer namespace. Both executables contain their own compiled copies of ProductsDataSet, ScannedProductsDataSet and the whole FamilTsdDB storage engine. Server and client were built from one shared code base. compiled
EKOS found 0 calls into any database provider (SqlClient, SqlServerCe, OleDb, …) in all 12 binaries. The typed TableAdapters read and write FamilTsdDB files, not SQL. The products.sdf SQL CE connection string in the settings is never used. compiled graph
A working day for one terminal, reconstructed from the call graph. Steps 1–3 and 6–7 run on the desktop, steps 4–5 on the handheld.
The operator presses “Import product file” or “Import document file”. The handlers call DataLoaderClass.AutoLoadProduct / AutoLoadDoc, which start the import on a background thread (LoadFile, 0x060002C5). A second import cannot start while one is running: “Load in progress!”. compiled
BeginImport clears the target tables (CleanProducts/CleanDocs) and reads the file as windows-1251. It dispatches each line to a fixed-width or delimited parser depending on the ImportFileTypeIsFixed setting (AddFixedStringProducts, AddDelimetedStringDocs, …). Finally it commits through the table adapters' Update. Lines with a bad barcode are skipped with “Invalid barcode - line skipped”. Other errors either abort or continue, depending on BreakOnError. compiled
The upload handler (“Upload to terminal”) first calls GetDBDate and compares the catalogue date with today. If the catalogue is old, it warns: “Warning: the catalogue … is dated {0}! Are you sure you want to load old data?”. It then connects over RAPI, deletes any existing database files on the device, and streams each file with BeginCopyFileToDevice behind a cancellable progress dialog. When the device connects, ActiveSync_Active also syncs the terminal clock (RAPI.SetDeviceTime). compiled
Program.Main loads Settings.xml next to the executable. If the file is missing, it creates a settings row with built-in defaults: printer 00:03:7a:32:4c:55, COM 9, storage path \Storage Card\tsdfamilia, StorageMemorySize 15000. The main form then shows the numbered menu and starts the scanner (ActionsClass.BeginScan). compiled observed
Staff pick a workflow and scan. Each accepted scan updates the in-memory ScannedBarcodes table. BeginScan 0x06000167 subscribes to that table's RowChanged/ColumnChanged events. Their handlers call WriteDbTxt 0x0600016A, which appends the row to scannedbarcodes.txt as a |-separated line and to register.txt, then flushes. A crash or battery loss therefore does not lose a scan. compiled
“Download from terminal” copies the scanned-data files back with RAPI.CopyFileFromDevice. It reports every file that failed to copy. compiled
UploadResults writes scannedbarcodes.txt (7 fields, {0}|…|{6}) and register.txt ({0},{1,11:D}, {2,7:D}) into LocalFilePath. It copies each one to RemoteFilePath as {name}_{yyyyMMddhhmmss}.txt. If EraseTerminalDB is set, DeleteOldDB then deletes the scanned files on the terminal. compiled
A Windows Forms tray application (notifyIcon1, “TSD Server”) with a status log (richTextBox1). It has two modes, chosen in Program.Main 0x060002B5. compiled
Opens Form1 and registers an IPC remoting channel at ipc://localhost:9090/RemoteObject.rem that exposes RemoteObject.Show. This is most likely a single-instance mechanism: a second launch asks the running window to show itself. compiled reading
/cConfigures log4net from log4netconfig.xml, runs AutoLoadProduct and then AutoLoadDoc, and waits up to 900,000 ms (15 min) for each. On timeout it logs ERROR LOAD PRODUCT - TIMEOUT / ERROR LOAD DOCS - TIMEOUT, emails AddressToList through SendMailClass, and returns an ERRORLEVELS exit code. It is built to run from a scheduler. In both modes, DataLoaderClass_OnFinishImport 0x060002C7 also emails the import log, subject “Data load status”, after every import. compiled
| Component | Token | What it does |
|---|---|---|
| Form1 | 0x02000003 | Main window: import buttons, upload/download, ActiveSync connect/disconnect/IP-change handlers, RAPI copy progress, tray icon. 29 methods; most complex is the upload handler (cyclomatic complexity 15). |
| DataLoaderClass | 0x0200002F | Import pipeline: threaded load, fixed and delimited parsers for products and docs, ParseColumn (complexity 12), catalogue date (GetDBDate, NoDateException), and result export (UploadResults). Raises StartImport/ProcessImport/FinishImport/FailedImport events. |
| SendMailAttach.SendMailClass | 0x02000038 | SMTP sender using the default network credentials, KOI8-R body encoding and an application/vnd.ms-excel attachment. Also usable stand-alone: its usage text is SendMailAttach Subject Body To Attachment_FileName. |
| Compressor | 0x02000037 | GZip plus BinaryFormatter helpers. No method in any binary calls them. graph |
| SettingsForm | 0x0200001C | Import format editor: column widths, field delimiter, file type (fixed/delimited), date format and separator, decimal separator, database path, and the program path on the terminal. |
| Properties.Settings | 0x02000039 | Persisted server settings. See §14. |
A .NET Compact Framework 2.0 Windows Forms application driven entirely from the keypad. Menus are numbered and hot keys are announced on screen, for example “Enter – Yes, FN+CLR – No” and “F4 - Results”. compiled
| Key | Main-menu item MainForm · 0x0200001D | Opens |
|---|---|---|
| 1 | Price check | ViewProductForm |
| 2 | Stock-taking | InventarForm |
| 3 | Internal box receiving | IncomeForm |
| 4 | Truck receiving | TtnForm |
| 5 | Settings | SettingsForm |
| 6 | Delivery notes | InventarForm (SimpleIncome mode) |
| 7 | Returns | ReturnForm |
| 0 | Exit (only when EnableExit) | Application.Exit |
The labels are the button captions, translated from Russian compiled. MenuEvents 0x0600013C constructs exactly the forms in the right-hand column compiled. The one-to-one pairing of key and form is inferred from caption order and each form's own title strings, for example TtnForm's title is “Truck receiving”. reading
| Type | Token | Methods | Responsibility |
|---|---|---|---|
| ActionsClass | 0x02000022 | 96 | Singleton core: action dispatch, document open/close, scan journal, lookups, sounds, vibration, label printing. Largest type in the app. |
| ViewProductForm | 0x0200000E | 18 | Product screen used by several workflows. Holds the two most complex methods in the system (§16). |
| BTPrintClass | 0x02000038 | 46 | Bluetooth printer discovery, pairing, serial-port I/O, reconnect and print queue. |
| ScanClass | 0x0200002F | 13 | Barcode reader lifecycle on a background thread; raises Scanned. |
| InventarForm · IncomeForm · TtnForm · ReturnForm | — | 10–12 | One form per workflow (§8). TtnForm hands each truck's boxes to IncomeForm. ReturnBoxForm is unreachable (§16). |
| ViewBoxForm · ViewInventarForm · ViewTtnForm · ViewDocsForm · ViewLoadDateForm | — | 6–8 | Result and status viewers (F4 screens, data information). |
| NativeClass | 0x0200006A | 15 | P/Invoke: device ID via KernelIoControl, OEM info, memory division, WCE_PlaySound. |
| FamilTsdDB.* | 0x02000054–5E | ~100 | Embedded file database engine (§12). |
Each workflow below is described from its form's handlers and the verbatim prompts and messages compiled into them. compiled
Scan a product or type its Navision code (“Navision code”). The screen shows name, article, OldPrice/NewPrice (formatted ######.00) and planned vs. actual quantity. F1 / F2 print a label with template 1 or 2 (“F1-Print1”, “F2-Print2”). F4 lists every document the product appears in (ViewDocsForm). A product that is also part of a return is flagged “This item is part of a return”.
Start by scanning the “new count sheet barcode”. The count is opened (OpenInv) or resumed (“Continue the count?”). Items are then scanned into it, and F3 closes it (“F3-Close count”). A count that is already closed is refused (“Count … already completed!”). A wrong location barcode gives “Barcode {0}: wrong address!”. The InventarMode enum distinguishes UseReturns / DontUseReturns.
Scan a box barcode. The terminal finds the delivery note it belongs to and shows “Note No. {0}: {1} boxes”. It rejects foreign boxes (“This is a foreign box!”), boxes already accepted, and barcodes that are not box barcodes. F1 accepts a box in full (“F1-accept in full”). Running totals show articles and pieces planned vs. accepted until “BOX FULLY ACCEPTED”.
Scan the TTN (consignment note) barcode. A TTN for another store is rejected (“Waybill is not for this store!”), as is a closed one (“Waybill already closed!”). A TTN moves through WAYBILL TO ACCEPT → WAYBILL BEING RECEIVED → WAYBILL ACCEPTED, per CheckStatus. Its boxes are then received box by box (CarScanMode: CarsScan / BoxScan). ViewTtnForm shows the truck as a tree of boxes with accepted/total counts.
The same form as stock-taking, in InventarFormMode.SimpleIncome. Enter or scan a delivery-note number (“Enter note No.”). Start or continue it, scan items against the plan, then close it (“Do you want to close the note?”).
Scan a product. The terminal lists every open return that includes it (FindAllReturnsByProduct), or shows “No returns found”. Returned goods are packed into return boxes (CreateNewReturnBox, CheckOpenedReturnBox, CloseReturnBoxAction). A box that is already closed is refused: “Box {0} already closed”. A dedicated ReturnBoxForm exists in the binary, but nothing opens it (§16).
1: find and pair the Bluetooth printer (SearchPrinterForm). 2: clear scanned data, with a two-step confirmation (“After clearing, all previously scanned data will be unavailable!”). This deletes scannedbarcodes.txt and register.txt. 3: data information (ViewLoadDateForm): last load date and a database health check (TestDB, CheckDbFile).
Two dialogs, ChangeQtyForm and MultiplyForm, gated by EnableChgQty (read by the result viewers) and EnableChgMlt (read by the product screen). They validate input (“Quantity out of range”, “Invalid format”). In the product screen, undoing the last scan asks for confirmation (“Reduce code {0} … from quantity {0} to quantity {1}?”) and refuses to go below zero (“Cannot reduce any further!”).
A scan's outcome is not hard-coded per screen. ActionsClass.InvokeAction(ActionCode, ProductsTblRow, DocsTblRow) 0x0600018D dispatches through an ActOnProduct delegate to one handler per action code. The document row carries per-document behaviour in LabelCode, MusicCode, VibroCode and Priority. So the back office, by preparing the document file, decides what the terminal does when an item is scanned. compiled reading
TSDUtils.ActionCode members graph | Display labels, translated (ActionCodeDescription) compiled |
|---|---|
| NoAction · Returns · Reprice · Remove · InventoryGlobal · QuickHelp · InventoryLocal · IncomeBox · CloseInventar · Cars · SimpleIncome · BoxWProducts · CarsBoxes · CloseIncome · BoxIncomes · BoxReturns · ReturnBoxWProducts · CloseBoxReturns · ReturnsTTN · ReturnInInventory · StrangeBox · AlreadyAccepted · NotFound · DocNotFound | NO ACTION · RETURN · REPRICING · TRANSFER · Inventory, global · QUICK HELP · Inventory, spot check · Box receiving · Close global inventory · Deliveries (waybill) · Goods receiving · Notes and boxes · Trucks and boxes · Close note · Notes · Return boxes and goods · Return notes and boxes · Close return box · Return notes · Item not found · Document not found |
Enum members come from ekos_neighborhood on the ActionCode type. Labels are the string constants of ActionCodeDescription 0x02000007, in declaration order. They pair up closely: Returns/RETURN, Reprice/REPRICING, Remove/TRANSFER, QuickHelp/QUICK HELP. EKOS does not read enum constant values, so the exact numeric mapping is not asserted.
| Handler | Token | Behaviour |
|---|---|---|
| RepriceActionProc | 0x0600017B | Finds the scan row. Plays the document's sound and vibration, prints a label using the document's LabelCode template (ActionCodeDescription.GetShablon → PrintLabel), and increments FactQuantity. |
| SimpleIncomeActionProc · InventoryGlobalActionProc · InventoryLocalActionProc | 0x0600017F · 0x0600017E | Adds or increments the scan row for (barcode, DocType, DocId) with the document's plan quantity and priority, then signals completion. |
| BoxWProductsActionProc · AcceptFullBoxWProductsActionProc · IncomeBoxAction · IncomeCarBoxAction | 0x06000181 · 0x06000182 | Box and truck receiving: per-item or whole-box acceptance. |
| ReturnActionProc · ReturnBoxWProductsActionProc · CloseReturnBoxAction | 0x06000180 · 0x060001B1 | Returns and return boxes. |
| RemoveActionProc · NoActionProc | — | Transfer; no action. |
| NotFoundActionProc · DocNotFoundActionProc | 0x06000184 | Unknown product or document: warning sound and vibration only. |
| UndoLastScannedPosition | 0x0600019C | Decrements FactQuantity of the last scan. |
PlaySound(code) reads SOUND_{code}.def next to the executable, parses each line into a SoundDef (type, frequency, time) and drives Calib.SystemLibNet.Api.SysPlayBuzzer. Vibration does the same with VIBRO_{code}.def. The folder ships codes 10, 12 and 250 for both. Their observed contents document the SysPlayBuzzer/SysPlayVibrator parameters. compiled observed
PrintLabel reads LABEL_{n}.DEF, replaces placeholders with ReplaceAttr, and sends the result to the printer. The placeholders are <GOODS_ATTRIBUTE_x>, <DOCS_ATTRIBUTE_x>, <SCAN_ATTRIBUTE_x> and <SYSTEMDATE>; ReplaceAttr's numeric constants 60 and 62 are the character codes of < and >. Values are formatted by type (dd.MM.yyyy, ######.00) and encoded with CustomEncodingClass, a Cyrillic code page embedded as a string table. On a busy printer it retries, up to WaitPrintTimeDefault. No LABEL_*.DEF file is present in this release folder. compiled graph
The path from trigger press to journal line, following resolved Calls edges. compiled
InitScan configures the reader through OBReadLibNet: symbologies, scan key, buffer type, notification, buzzer and vibrator. It then calls OBROpen and starts a thread. The thread blocks on SysWaitForEvent("OBRScanningEvent", 2000), reads the text, and raises Scanned. Supported symbologies include Code39, NW-7, UPC/EAN, ITF, Code93, Code128, MSI, IATA and EAN-13/GTIN.
The active form's handler (OnScanned / Scanned) looks up the product (SearchBarcode, GetProductRowByNavCode) and the document (GetDataByDocIdAndType, FindByDocIdAndDocType).
DoAction (complexity 38, 33 branches) decides between the outcomes whose messages it carries: “Item already received: {0} of {1}”, “Receive {0} more pcs”, “Item is not in this box!”, “DEFECTIVE”, “Stock-taking mode”, “Delivery-note mode”. It then calls ActionsClass.InvokeAction.
AddScannedRow finds or creates the row keyed by (Barcode, DocType, DocId) and calls AcceptChanges. The table's change events fire WriteDbTxt 0x0600016A, which appends an 8-field line ({0}|…|{7}, UTF-8) to the journal and a line to register.txt. Opening and closing documents, boxes and trucks write their own marker lines directly (OpenInv, CloseInv, CloseDoc, CloseCarAction, CreateNewReturnBox, CloseReturnBoxAction, IncomeBoxAction).
The ActionCompleted event updates planned vs. actual counts on screen. It plays the document's sound, and when a box is complete it shows “Box on note … fully received!”.
Blast radius: ekos_impact on AddScannedRow, following Calls in reverse, finds 29 methods that write scan records through it: 14 direct callers, and the deepest 4 hops away (the query bound was 5, so this is the complete set). Among them are DoAction, navCodeTB_KeyDown, OpenInv/CloseInv, every *ActionProc, CheckStatus, OnIncomeScanned and CreateNewReturnBox. Any change to the scan-record key or format has to be checked against all of them. graph (raw result)
Typed ADO.NET DataSets, recovered from their generated row accessors (get_X/IsXNull) and schema strings. compiled
Barcode · NavCode · Article · ProductName · Country · Structure · OldPrice · NewPrice · MarketPrice · Message · Message2 · AcceptDefect
MarketPrice, Message2 and AcceptDefect exist only in the client build; the server writes the other 9 columns.
DocId · DocType · NavCode · DocumentDate · Quantity · Priority · LabelCode · MusicCode · VibroCode · Text1 · Text2 · Text3
One row per (document, product): planned quantity plus the per-document print, sound and vibration behaviour.
Barcode · DocId · DocType · PlanQuanity · FactQuantity · ScannedDate · TerminalId · Priority
The result of the day's work. Primary lookup is (Barcode, DocType, DocId). "PlanQuanity" is misspelled in the schema itself.
19 typed columns (§14) plus a free-form Name/Value table.
ProductsBinTbl's column set is combined with FieldsLength in DataLoaderClass.SetFormats 0x060002C2 to define the fixed-width import layout. DocsBinTbl/DocsBinTbl1 (adding Shablon, RePriceDate and ReturnDate) have no reader in the call graph.
View model rendered as “Document {0} No. {1} dated {2} … Plan: {6}, Actual: {7}”.
FamilTsdDB is an in-house embedded database compiled into both executables. It stores each DataTable as a set of files, and the typed TableAdapters (BaseTableAdapter: Open/Fill/Update/Close) sit on top of it. compiled
{0}|{1}|{2}|{3}|{4}|{5}), taken from the DataTable's name, type, max length, nullability and uniqueness (DataTable..ctor 0x06000419).BinaryWriter). They are read back by seeking and BitConverter.ToUInt16-prefixed reads (Fill 0x06000426, Write 0x0600041C).IndexItems. Lookups: FindByPk, FindByIndex, FindByIndexes, FindAllByPartIndexes (prefix match), plus direct-scan and reverse-scan fallbacks. The most complex method in the engine is the index iterator FindIndexes (complexity 17).| Text file | Written by | Format | Example (observed) |
|---|---|---|---|
| scannedbarcodes.txt (terminal journal) | TSDClient ActionsClass | 8 fields, |, UTF-8 | 6600000000001|6600000000001|8|0|02.01.2003|0|0|0 |
| scannedbarcodes.txt (desktop export) | TSDServer UploadResults | 7 fields, | | 2900655000005|02: 15.06.11|2|1|29.06.2011|1|0 |
| register.txt | both | {0},{1,11:D}, {2,7:D} | 2896459000009, 1, 1 |
Field order is read from the getter call order. UploadResults exports Barcode, DocId, DocType, FactQuantity, ScannedDate, TerminalId, Priority. The terminal's WriteDbTxt journals Barcode, DocId, DocType, FactQuantity, ScannedDate, TerminalId, Priority, PlanQuanity. Both observed samples fit. compiled observed reading The journal's first line uses the document's own barcode as both Barcode and DocId, which is the open-document marker OpenInv writes. Its 660… prefix matches the "660" constant in InventarForm, so stock-taking count sheets most likely use a 660 barcode range. reading OpenScanned 0x06000163 rebuilds the in-memory table from the journal whenever a workflow is opened from the menu or an open document or box is looked up; its numeric constants 10 and 124 are '\n' and '|'. compiled
OBRLoadConfigFile, OBRSetDefaultSymbology, OBRSetScanningKey, OBRSetScanningNotification, OBROpen, OBRClearBuff, OBRSaveConfigFile. Scanning can be paused and resumed around dialogs (PauseScan/ResumeScan). Errors reported: "Failed to connect to the scanner." and "Trigger keys are being used…". compiled
BTInitialize → BTInquiry (device search) → BTRegisterDeviceInfo → BTSetDefaultDevice → BTConnectSerial (BTPORT_SERIAL). It then opens COM{n}: from BTComPort and writes through SerialPort. The connect method's numeric constant 19200 is most likely the baud rate reading. A string in the same method reads "Extech BT printer found!". Every step is logged to BTLog.txt, and a lost connection opens BTConnectionErrorForm with reconnect. compiled
SysPlayBuzzer and the vibrator API, parameterised by the .def files. SoundCodes members: B_CLICK, B_TAP, B_WARNING, B_ALARM, B_SCANEND, B_WIREREAD, B_CARDREAD, B_USERDEF. compiled graph
GetDeviceID can read the hardware ID with KernelIoControl (formatted {0:X8}-{1:X4}-{2:X4}-{3:X4}-…), but nothing calls it. The TerminalID stamped into scan rows and exported results comes from Settings.xml, so two terminals with the same settings file report the same ID. compiled graph
Settings.xml (SettingsDataSet.TypedSettings)| Setting | Meaning (from where it is used) | Observed value |
|---|---|---|
| TerminalID | Stamped on scan rows and exported results | — |
| DatabaseStoragePath | FamilTsdDB directory used by TestDB/CheckDbFile | \Storage Card\tsdfamilia |
| BTPrinterAddress · BTComPort | Paired printer MAC; virtual COM port for the printer | 00:03:7a:32:4c:55 · 9 |
| WaitPrintTimeDefault | Print retry wait in PrintLabel | — |
| DefaultRepriceShablon · BlueButtonShablon | Label templates used by the product screen's print keys (both read in navCodeTB_KeyDown) | — |
| StorageMemorySize | Storage/program memory split, applied at start-up: Program.Main → NativeClass.SystemStorageMemory → SetSystemMemoryDivision | 15000 |
| EnableExit · EnableWorkWOPrinter | Allow exit from the menu; allow the product screen to work without a printer (read in ViewProductForm_Load) | — |
| EnableChgQty · EnableChgMlt | Allow quantity edit (read by the result viewers) / multiply (read by the product screen) | — |
| BaseDate | Date baseline, read by the table adapters and ActionsClass | 2000-01-01 |
| DatabaseFileName · ProductsConnectionString · VibarationOn · ScanSoundNotifyOn · ComBufferSize · CurrentDate | Never read. Their getters have no incoming Calls edge from any method in any binary. They are written as defaults and persisted, but nothing acts on them. This includes the SQL CE database name and connection string. graph | products.sdf · Data Source=|DataDirectory|\Products.sdf · false · false · — · — |
Setting names and defaults are compiled into TypedSettingsDataTable and Program.Main compiled. "Read by" is the set of direct callers of each getter, from ekos_impact over resolved Calls edges graph. Values come from the observed Settings.xml excerpt observed. "—" means the excerpt EKOS stored was truncated before that element.
TSDServer.Properties.SettingsLocalFilePath · RemoteFilePath · TSDDBPAth · EraseTerminalDB · ImportProductsEnabled · ImportDocsEnabled · ImportFileTypeIsFixed · FieldsLength · FieldDelimeter · DateSeparator · ShortDatePattern · NumberDecimalSeparator · BaseDate · BreakOnError · SettingsEnabled · SmtpClient · AddressFrom · UserNameFrom · AddressToList
| File | What it is | Evidence |
|---|---|---|
| TSDClient.exe · TSDServer.exe | The two applications | compiled |
| TSDClient - Copy.exe · TSDClient.ex_ | Copies of the handheld app. The .ex_ is recorded as a file only; the binary observer does not pick it up. | compiled |
| TSDClient.pdb | Debug symbols (650 KB). EKOS does not read PDBs. | observed |
| *.dll (11) | See §3. MCSSLib.dll is native ARM code. | compiled |
| Settings.xml · _Settings.xml · Settings - Copy.xml | Terminal settings plus two variants | observed |
| SOUND_10/12/250.def · VIBRO_10/12/250.def | Buzzer and vibrator patterns per MusicCode/VibroCode | observed compiled |
| scannedbarcodes.txt · scannedbarcodes.txt1 · register.txt | Sample results: a desktop-format export (2011 dates) and a terminal journal (2003 dates) | observed |
| BTLog.txt | Bluetooth printer log. Its 1/3/2003 timestamps suggest the device clock was unset. | observed |
| tsdfamilia.zip | 877-byte archive; contents not observed | observed |
| enkaTCdaily.xml | An SQL Server Reporting Services export (reportserver, "JANUS Head Office"). Unrelated to TSD and not referenced by any binary. | observed graph |
| Method | Binary · token | Complexity | Why it matters |
|---|---|---|---|
| ViewProductForm.navCodeTB_KeyDown | client · 0x06000051 | 42 | Every key on the product screen: print, close count, close note, undo, add quantity |
| ViewProductForm.DoAction | client · 0x0600004B | 38 | The per-scan business rules (§10) |
| ViewBoxForm.RefreshData | client · 0x06000443 | 24 | Box result listing |
| IncomeForm.textBox1_KeyDown | client · 0x06000492 | 22 | Box receiving keys. An identical copy sits in the unreachable ReturnBoxForm (0x06000156). |
| BTPrintClass.TestPrint | client | 21 | Printer diagnostics |
| ActionsClass.ReplaceAttr | client · 0x06000178 | 18 | Label template substitution |
| DataLoaderClass.BeginImport | server · 0x060002CA | 15 | All inbound data passes through here |
Three builds of the handheld app sit side by side (.exe, - Copy.exe, .ex_) with different type counts, plus three settings files. Which one is deployed cannot be told from the folder. compiled
PrintLabel requires LABEL_{n}.DEF, and no such file is in this folder. Printing depends on files deployed some other way. compiled graph
ImagerLibNet, MoFlinkLibNet and ControlsLib have no dependents. ControlsLib itself references NetworkLib and TsdCommandsLib, which are not in the folder. Its NewForm uses a NetMan command/reply protocol, a trace of a different, networked client. graph compiled
ActionsClass holds 96 methods: dispatch, persistence, lookups, device feedback and printing. It is the one type that nearly every workflow calls, and 29 methods reach its scan-record writer (§10). compiled graph
A specific printer MAC (00:03:7a:32:4c:55), COM port 9 and \Storage Card paths are compiled into Program.Main as fall-backs. A terminal without Settings.xml silently targets that one printer. compiled
Six of the terminal's 19 typed settings are never read. They include both feedback switches (VibarationOn, ScanSoundNotifyOn) and the SQL CE DatabaseFileName/ProductsConnectionString. Turning feedback off in Settings.xml changes nothing: sound and vibration follow the document's MusicCode/VibroCode instead. graph reading
ReturnBoxForm (a near-copy of IncomeForm, 11 methods) is never constructed, so the screen cannot be opened. Also never called: NativeClass.GetDeviceID, the server's Compressor, and the server's DocsBinTbl/DocsBinTbl1 tables. graph
Scan results travel and are archived as unencrypted text files, and are emailed with default network credentials. Nothing sensitive appears in the samples, but there is no integrity check on the exchange. compiled reading
EKOS's own Risk objects are all concentration risks on framework assemblies: mscorlib (12 dependents), System.Windows.Forms (8), System, System.Drawing (6), System.Data (5), System.Xml (4). For a .NET Compact Framework 2.0 application, they mostly say that the platform itself is the migration risk. graph
DoAction has 33 branches and which messages it can show, but not the precise predicate that selects each message.ActionCode numbers behind document DocTypes (such as 2, 5 and 8 in the samples) are not mapped.FieldsLength, FieldDelimeter) that are not in the folder.call_targets property keeps at most 32 distinct targets (Program.Main has more), with no truncation marker. Every "never called" and "read by" statement here therefore comes from resolved Calls edges through ekos_impact, which are complete for code inside these binaries.MCSSLib.dll (native ARM), TSDClient.pdb and tsdfamilia.zip are recorded but not read.[binary-reconstruction] stage, which proposes business rules scored for confidence, was not used; only local models were available. Every reading in this document is a human-auditable join of compiled facts, not model output.git clone --filter=blob:none --sparse https://github.com/alexeyban/tsd.git
cd tsd && git sparse-checkout set SmartDeviceProject3/SmartDeviceProject2/SmartDeviceProject2/bin/Release
ekos init
ekos build && ekos recover && ekos resolve --force && ekos compile && ekos commit
# recover: 12 binaries, 888 types, 8327 methods, 7134 fields, 174 I/O boundaries
# 10956 call edges resolved
# resolve --force: one known false conflict (the "System" assembly vs. a field named "system")ekos docs generate --layout curated # README / Architecture / API + 9,283 entity pages ekos docs generate --layout solution-architect # risk report, onboarding guide, findings memo
A copy of the top-level generated reports is kept in examples/tsd/generated/.
ekos mcp serve --workspace .
# ekos_ekl FIND Object WHERE kind CONTAINS 'BinaryType' AND name = 'TSDServer.ViewProductForm'
# ekos_binary_explain {id} → members, complexity, constants, call targets, I/O, provenance
# ekos_impact {id, direction: "dependents", kinds: ["Calls"]}
# ekos_dependents {id of BluetoothLibNet} → TSDClient ×2
The ekos_binary_explain output behind this document is kept for 22 key types in examples/tsd/binary-explain/.