OneOCR Dev commited on
Commit
366e8c3
·
1 Parent(s): 7cecd12

feat: add diagnostic debug loader for Wine troubleshooting

Browse files
test_wine_colab.ipynb CHANGED
@@ -28,11 +28,23 @@
28
  "metadata": {},
29
  "outputs": [],
30
  "source": [
31
- "# 1. Install Wine + MinGW\n",
32
- "!dpkg --add-architecture i386\n",
33
- "!apt-get update -qq\n",
34
- "!apt-get install -y -qq wine64 mingw-w64 > /dev/null 2>&1\n",
35
- "!wine64 --version"
 
 
 
 
 
 
 
 
 
 
 
 
36
  ]
37
  },
38
  {
@@ -42,13 +54,15 @@
42
  "metadata": {},
43
  "outputs": [],
44
  "source": [
45
- "# 2. Initialize Wine prefix (suppress noise)\n",
46
  "import os\n",
47
  "os.environ['WINEDEBUG'] = '-all'\n",
48
  "os.environ['WINEPREFIX'] = '/root/.wine'\n",
49
  "os.environ['WINEARCH'] = 'win64'\n",
50
- "!wineboot --init 2>/dev/nulla\n",
51
- "print('Wine prefix initialized')"
 
 
52
  ]
53
  },
54
  {
@@ -58,10 +72,13 @@
58
  "metadata": {},
59
  "outputs": [],
60
  "source": [
61
- "# 3. Clone repo from HuggingFace (code only — DLLs not in repo)\n",
 
62
  "!git lfs install\n",
63
- "!git clone https://huggingface.co/MattyMroz/oneocr /content/oneocr 2>/dev/null || echo \"Already cloned\"\n",
64
  "!mkdir -p /content/oneocr/ocr_data\n",
 
 
65
  "!ls -la /content/oneocr/ocr_data/ 2>/dev/null || echo \"ocr_data/ is empty — upload DLLs in next cell\""
66
  ]
67
  },
@@ -87,27 +104,55 @@
87
  "from pathlib import Path\n",
88
  "\n",
89
  "ocr_data = Path('/content/oneocr/ocr_data')\n",
90
- "needed = ['oneocr.dll', 'oneocr.onemodel', 'onnxruntime.dll']\n",
 
 
 
 
 
 
 
91
  "\n",
92
- "# Przenieś z /content/ (domyślny upload) do ocr_data/\n",
93
- "for f in needed:\n",
94
- " src = Path(f'/content/{f}')\n",
95
  " dst = ocr_data / f\n",
96
- " if src.exists() and not dst.exists():\n",
97
- " shutil.move(str(src), str(dst))\n",
98
- " print(f' ✅ Przeniesiono: {f}')\n",
99
- " elif dst.exists():\n",
100
  " print(f' ✅ Już jest: {f} ({dst.stat().st_size / 1e6:.1f} MB)')\n",
101
- " else:\n",
102
- " print(f' ❌ BRAK: {f} — wrzuć plik!')\n",
103
- "\n",
104
- "# Sprawdź\n",
105
- "missing = [f for f in needed if not (ocr_data / f).exists()]\n",
106
- "if missing:\n",
107
- " print(f'\\n⚠️ Brakuje: {missing}')\n",
108
- " print('Wrzuć pliki przez panel \"Files\" po lewej stronie, potem uruchom tę komórkę ponownie.')\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  "else:\n",
110
- " print(f'\\n🎉 Wszystkie pliki na miejscu! Lecimy dalej.')"
111
  ]
112
  },
113
  {
@@ -128,10 +173,60 @@
128
  "metadata": {},
129
  "outputs": [],
130
  "source": [
131
- "# 6. Compile C loader with MinGW cross-compiler\n",
 
132
  "!x86_64-w64-mingw32-gcc -O2 -o /content/oneocr/tools/oneocr_loader.exe /content/oneocr/tools/oneocr_loader.c\n",
133
- "!ls -la /content/oneocr/tools/oneocr_loader.exe\n",
134
- "print('✅ C loader compiled OK')"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  ]
136
  },
137
  {
@@ -141,7 +236,7 @@
141
  "metadata": {},
142
  "outputs": [],
143
  "source": [
144
- "# 7. 🧪 TEST: Run C loader via Wine on a single image\n",
145
  "import subprocess, json, os\n",
146
  "from PIL import Image\n",
147
  "from pathlib import Path\n",
@@ -192,7 +287,7 @@
192
  "metadata": {},
193
  "outputs": [],
194
  "source": [
195
- "# 8. 🧪 FULL TEST: Run on ALL 19 test images\n",
196
  "import time\n",
197
  "\n",
198
  "test_dir = Path('/content/oneocr/working_space/input')\n",
@@ -234,7 +329,7 @@
234
  "if fail == 0:\n",
235
  " print('🎉 Wine bridge on Linux: WORKS! 100% accuracy identical to Windows DLL.')\n",
236
  "else:\n",
237
- " print(f'⚠️ {fail} failures — check Wine/DLL setup')"
238
  ]
239
  },
240
  {
@@ -244,7 +339,7 @@
244
  "metadata": {},
245
  "outputs": [],
246
  "source": [
247
- "# 9. 🧪 TEST: Unified engine (auto-selects Wine backend on Linux)\n",
248
  "import sys\n",
249
  "sys.path.insert(0, '/content/oneocr')\n",
250
  "\n",
 
28
  "metadata": {},
29
  "outputs": [],
30
  "source": [
31
+ "# 1. Install Wine + MinGW (use WineHQ repo for latest stable)\n",
32
+ "import subprocess, os\n",
33
+ "\n",
34
+ "# Add WineHQ repo for latest stable Wine (Ubuntu's stock is old)\n",
35
+ "cmds = [\n",
36
+ " 'dpkg --add-architecture i386',\n",
37
+ " 'mkdir -pm755 /etc/apt/keyrings',\n",
38
+ " 'wget -qO /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key 2>/dev/null || true',\n",
39
+ " 'apt-get update -qq',\n",
40
+ " 'apt-get install -y -qq wine64 mingw-w64 > /dev/null 2>&1',\n",
41
+ "]\n",
42
+ "for cmd in cmds:\n",
43
+ " subprocess.run(cmd, shell=True, capture_output=True)\n",
44
+ "\n",
45
+ "# Show Wine version\n",
46
+ "!wine64 --version\n",
47
+ "!x86_64-w64-mingw32-gcc --version | head -1"
48
  ]
49
  },
50
  {
 
54
  "metadata": {},
55
  "outputs": [],
56
  "source": [
57
+ "# 2. Initialize Wine prefix (64-bit, suppress noise)\n",
58
  "import os\n",
59
  "os.environ['WINEDEBUG'] = '-all'\n",
60
  "os.environ['WINEPREFIX'] = '/root/.wine'\n",
61
  "os.environ['WINEARCH'] = 'win64'\n",
62
+ "!wineboot --init 2>/dev/null\n",
63
+ "!echo \"Wine prefix initialized\"\n",
64
+ "# Verify Wine can run basic exe\n",
65
+ "!echo 'int main(){return 0;}' > /tmp/test.c && x86_64-w64-mingw32-gcc -o /tmp/test.exe /tmp/test.c && wine64 /tmp/test.exe && echo \"Wine runs MinGW executables OK\""
66
  ]
67
  },
68
  {
 
72
  "metadata": {},
73
  "outputs": [],
74
  "source": [
75
+ "# 3. Clone repo from HuggingFace\n",
76
+ "!pip install -q huggingface_hub 2>/dev/null\n",
77
  "!git lfs install\n",
78
+ "!git clone https://huggingface.co/MattyMroz/oneocr /content/oneocr 2>/dev/null || (cd /content/oneocr && git pull)\n",
79
  "!mkdir -p /content/oneocr/ocr_data\n",
80
+ "!ls -la /content/oneocr/tools/\n",
81
+ "print(\"\\n--- ocr_data/ contents ---\")\n",
82
  "!ls -la /content/oneocr/ocr_data/ 2>/dev/null || echo \"ocr_data/ is empty — upload DLLs in next cell\""
83
  ]
84
  },
 
104
  "from pathlib import Path\n",
105
  "\n",
106
  "ocr_data = Path('/content/oneocr/ocr_data')\n",
107
+ "needed = {\n",
108
+ " 'oneocr.dll': 40_000_000, # ~40 MB\n",
109
+ " 'oneocr.onemodel': 50_000_000, # ~56 MB \n",
110
+ " 'onnxruntime.dll': 10_000_000, # ~13 MB\n",
111
+ "}\n",
112
+ "\n",
113
+ "# Search multiple possible locations\n",
114
+ "search_dirs = [Path('/content'), Path('/root'), Path('/tmp')]\n",
115
  "\n",
116
+ "for f, min_size in needed.items():\n",
 
 
117
  " dst = ocr_data / f\n",
118
+ " if dst.exists() and dst.stat().st_size > min_size:\n",
 
 
 
119
  " print(f' ✅ Już jest: {f} ({dst.stat().st_size / 1e6:.1f} MB)')\n",
120
+ " continue\n",
121
+ " \n",
122
+ " # Find the file\n",
123
+ " found = False\n",
124
+ " for d in search_dirs:\n",
125
+ " src = d / f\n",
126
+ " if src.exists() and src.stat().st_size > min_size:\n",
127
+ " shutil.copy2(str(src), str(dst))\n",
128
+ " print(f' ✅ Skopiowano: {f} ({dst.stat().st_size / 1e6:.1f} MB)')\n",
129
+ " found = True\n",
130
+ " break\n",
131
+ " \n",
132
+ " if not found:\n",
133
+ " if dst.exists():\n",
134
+ " size = dst.stat().st_size\n",
135
+ " if size < 1000:\n",
136
+ " # Likely git LFS pointer\n",
137
+ " print(f' ❌ {f} — to git LFS pointer ({size} B)! Wrzuć prawdziwy plik.')\n",
138
+ " with open(dst) as fh:\n",
139
+ " print(f' Zawartość: {fh.read(100)[:80]}...')\n",
140
+ " else:\n",
141
+ " print(f' ⚠️ {f} istnieje ale mały ({size / 1e6:.1f} MB) — sprawdź!')\n",
142
+ " else:\n",
143
+ " print(f' ❌ BRAK: {f} — wrzuć plik!')\n",
144
+ "\n",
145
+ "# Final check\n",
146
+ "print()\n",
147
+ "all_ok = True\n",
148
+ "for f, min_size in needed.items():\n",
149
+ " dst = ocr_data / f\n",
150
+ " if not dst.exists() or dst.stat().st_size < min_size:\n",
151
+ " all_ok = False\n",
152
+ "if all_ok:\n",
153
+ " print('🎉 Wszystkie pliki na miejscu!')\n",
154
  "else:\n",
155
+ " print('⚠️ Brakuje plików wrzuć je i uruchom tę komórkę ponownie.')"
156
  ]
157
  },
158
  {
 
173
  "metadata": {},
174
  "outputs": [],
175
  "source": [
176
+ "# 6. Compile BOTH loaders: debug + normal\n",
177
+ "!x86_64-w64-mingw32-gcc -O2 -o /content/oneocr/tools/oneocr_debug.exe /content/oneocr/tools/oneocr_debug.c\n",
178
  "!x86_64-w64-mingw32-gcc -O2 -o /content/oneocr/tools/oneocr_loader.exe /content/oneocr/tools/oneocr_loader.c\n",
179
+ "!ls -la /content/oneocr/tools/*.exe\n",
180
+ "print('✅ Both loaders compiled')"
181
+ ]
182
+ },
183
+ {
184
+ "cell_type": "code",
185
+ "execution_count": null,
186
+ "id": "2b76a011",
187
+ "metadata": {},
188
+ "outputs": [],
189
+ "source": [
190
+ "# 7. 🔍 DIAGNOSTYKA — Run debug loader to find exact failure point\n",
191
+ "import subprocess, os\n",
192
+ "\n",
193
+ "os.environ['WINEDEBUG'] = '-all'\n",
194
+ "\n",
195
+ "# Convert path for Wine\n",
196
+ "dll_dir_wine = 'Z:\\\\content\\\\oneocr\\\\ocr_data'\n",
197
+ "\n",
198
+ "print(\"=\" * 60)\n",
199
+ "print(\"DIAGNOSTYKA: Testowanie komponentów pod Wine\")\n",
200
+ "print(\"=\" * 60)\n",
201
+ "\n",
202
+ "# Run debug loader\n",
203
+ "result = subprocess.run(\n",
204
+ " ['wine64', '/content/oneocr/tools/oneocr_debug.exe', dll_dir_wine],\n",
205
+ " capture_output=True, text=True, timeout=120,\n",
206
+ " env={**os.environ, 'WINEDEBUG': '-all'}\n",
207
+ ")\n",
208
+ "\n",
209
+ "print(result.stdout)\n",
210
+ "if result.stderr:\n",
211
+ " print(\"--- STDERR ---\")\n",
212
+ " print(result.stderr[:1000])\n",
213
+ "\n",
214
+ "# Also run with Wine debug channels for bcrypt/ntdll\n",
215
+ "print(\"\\n\" + \"=\" * 60)\n",
216
+ "print(\"EXTRA: Wine debug trace (bcrypt + module loading)\")\n",
217
+ "print(\"=\" * 60)\n",
218
+ "result2 = subprocess.run(\n",
219
+ " ['wine64', '/content/oneocr/tools/oneocr_debug.exe', dll_dir_wine],\n",
220
+ " capture_output=True, text=True, timeout=120,\n",
221
+ " env={**os.environ, 'WINEDEBUG': '+bcrypt,+loaddll'}\n",
222
+ ")\n",
223
+ "# Only show relevant debug lines (not all the noise)\n",
224
+ "for line in result2.stderr.split('\\n'):\n",
225
+ " if any(kw in line.lower() for kw in ['bcrypt', 'cfb', 'fail', 'err:', 'fixme:', 'oneocr', 'onnxruntime', 'not implemented', 'not supported']):\n",
226
+ " print(line)\n",
227
+ "if result2.stdout != result.stdout:\n",
228
+ " print(\"\\nDiagnostic output:\")\n",
229
+ " print(result2.stdout[-500:])"
230
  ]
231
  },
232
  {
 
236
  "metadata": {},
237
  "outputs": [],
238
  "source": [
239
+ "# 8. 🧪 TEST: Run C loader via Wine on a single image\n",
240
  "import subprocess, json, os\n",
241
  "from PIL import Image\n",
242
  "from pathlib import Path\n",
 
287
  "metadata": {},
288
  "outputs": [],
289
  "source": [
290
+ "# 9. 🧪 FULL TEST: Run on ALL 19 test images\n",
291
  "import time\n",
292
  "\n",
293
  "test_dir = Path('/content/oneocr/working_space/input')\n",
 
329
  "if fail == 0:\n",
330
  " print('🎉 Wine bridge on Linux: WORKS! 100% accuracy identical to Windows DLL.')\n",
331
  "else:\n",
332
+ " print(f'⚠️ {fail} failures — check diagnostic output (cell 7) for details')"
333
  ]
334
  },
335
  {
 
339
  "metadata": {},
340
  "outputs": [],
341
  "source": [
342
+ "# 10. 🧪 TEST: Unified engine (auto-selects Wine backend on Linux)\n",
343
  "import sys\n",
344
  "sys.path.insert(0, '/content/oneocr')\n",
345
  "\n",
tools/oneocr_debug.c ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* oneocr_debug.c -- Diagnostic loader for Wine troubleshooting
2
+ * Compile: x86_64-w64-mingw32-gcc -O2 -o oneocr_debug.exe oneocr_debug.c
3
+ * Usage: wine64 oneocr_debug.exe <dll_dir>
4
+ *
5
+ * Tests each component separately:
6
+ * 1. File access (can we read oneocr.onemodel?)
7
+ * 2. DLL loading (oneocr.dll, onnxruntime.dll)
8
+ * 3. bcrypt AES-256-CFB128 (model decryption)
9
+ * 4. CreateOcrPipeline (full init)
10
+ */
11
+ #include <stdio.h>
12
+ #include <stdlib.h>
13
+ #include <string.h>
14
+ #include <windows.h>
15
+
16
+ /* bcrypt types */
17
+ typedef void* BCRYPT_ALG_HANDLE;
18
+ typedef void* BCRYPT_KEY_HANDLE;
19
+ typedef long NTSTATUS;
20
+
21
+ typedef NTSTATUS (*fn_BCryptOpenAlgorithmProvider)(BCRYPT_ALG_HANDLE*, const wchar_t*, const wchar_t*, unsigned long);
22
+ typedef NTSTATUS (*fn_BCryptSetProperty)(BCRYPT_ALG_HANDLE, const wchar_t*, unsigned char*, unsigned long, unsigned long);
23
+ typedef NTSTATUS (*fn_BCryptGenerateSymmetricKey)(BCRYPT_ALG_HANDLE, BCRYPT_KEY_HANDLE*, unsigned char*, unsigned long, unsigned char*, unsigned long, unsigned long);
24
+ typedef NTSTATUS (*fn_BCryptEncrypt)(BCRYPT_KEY_HANDLE, unsigned char*, unsigned long, void*, unsigned char*, unsigned long, unsigned char*, unsigned long, unsigned long*, unsigned long);
25
+ typedef NTSTATUS (*fn_BCryptDecrypt)(BCRYPT_KEY_HANDLE, unsigned char*, unsigned long, void*, unsigned char*, unsigned long, unsigned char*, unsigned long, unsigned long*, unsigned long);
26
+ typedef NTSTATUS (*fn_BCryptCloseAlgorithmProvider)(BCRYPT_ALG_HANDLE, unsigned long);
27
+ typedef NTSTATUS (*fn_BCryptDestroyKey)(BCRYPT_KEY_HANDLE);
28
+
29
+ /* DLL function types */
30
+ typedef long long (*fn_CreateOcrInitOptions)(long long*);
31
+ typedef long long (*fn_OcrInitOptionsSetUseModelDelayLoad)(long long, char);
32
+ typedef long long (*fn_CreateOcrPipeline)(const char*, const char*, long long, long long*);
33
+ typedef void (*fn_ReleaseOcrInitOptions)(long long);
34
+ typedef void (*fn_ReleaseOcrPipeline)(long long);
35
+
36
+ static void test_file_access(const char* dll_dir) {
37
+ printf("\n=== TEST 1: File Access ===\n");
38
+
39
+ char model_path[MAX_PATH];
40
+ snprintf(model_path, sizeof(model_path), "%s\\oneocr.onemodel", dll_dir);
41
+
42
+ /* Test CreateFileA */
43
+ HANDLE hFile = CreateFileA(model_path, GENERIC_READ, FILE_SHARE_READ, NULL,
44
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
45
+ if (hFile == INVALID_HANDLE_VALUE) {
46
+ printf(" FAIL: Cannot open model file: %s (error %lu)\n", model_path, GetLastError());
47
+
48
+ /* Try alternate paths */
49
+ printf(" Trying alternate paths...\n");
50
+ char alt1[MAX_PATH];
51
+ snprintf(alt1, sizeof(alt1), "%s/oneocr.onemodel", dll_dir);
52
+ hFile = CreateFileA(alt1, GENERIC_READ, FILE_SHARE_READ, NULL,
53
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
54
+ if (hFile != INVALID_HANDLE_VALUE) {
55
+ printf(" OK with forward slashes: %s\n", alt1);
56
+ } else {
57
+ printf(" FAIL with forward slashes too (error %lu)\n", GetLastError());
58
+ }
59
+ }
60
+
61
+ if (hFile != INVALID_HANDLE_VALUE) {
62
+ LARGE_INTEGER size;
63
+ GetFileSizeEx(hFile, &size);
64
+ printf(" OK: Model file opened. Size: %lld bytes (%.1f MB)\n",
65
+ size.QuadPart, size.QuadPart / 1e6);
66
+
67
+ if (size.QuadPart < 1000000) {
68
+ /* Read first 100 bytes to check if it's a git lfs pointer */
69
+ char buf[200] = {0};
70
+ DWORD read = 0;
71
+ ReadFile(hFile, buf, 100, &read, NULL);
72
+ if (strstr(buf, "version https://git-lfs") != NULL) {
73
+ printf(" *** WARNING: File is a Git LFS POINTER, not actual data! ***\n");
74
+ printf(" Content: %s\n", buf);
75
+ printf(" Run: git lfs pull\n");
76
+ } else {
77
+ printf(" WARNING: File seems too small for a model!\n");
78
+ }
79
+ }
80
+
81
+ /* Read first 16 bytes (header) */
82
+ SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
83
+ unsigned char header[16];
84
+ DWORD bytesRead = 0;
85
+ ReadFile(hFile, header, 16, &bytesRead, NULL);
86
+ printf(" Header (first 16 bytes): ");
87
+ for (int i = 0; i < 16; i++) printf("%02x ", header[i]);
88
+ printf("\n");
89
+
90
+ CloseHandle(hFile);
91
+ }
92
+
93
+ /* Check DLL files */
94
+ char dll_path[MAX_PATH], ort_path[MAX_PATH];
95
+ snprintf(dll_path, sizeof(dll_path), "%s\\oneocr.dll", dll_dir);
96
+ snprintf(ort_path, sizeof(ort_path), "%s\\onnxruntime.dll", dll_dir);
97
+
98
+ HANDLE h1 = CreateFileA(dll_path, GENERIC_READ, FILE_SHARE_READ, NULL,
99
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
100
+ if (h1 != INVALID_HANDLE_VALUE) {
101
+ LARGE_INTEGER s; GetFileSizeEx(h1, &s);
102
+ printf(" OK: oneocr.dll exists (%.1f MB)\n", s.QuadPart/1e6);
103
+ CloseHandle(h1);
104
+ } else {
105
+ printf(" FAIL: oneocr.dll not found at %s (error %lu)\n", dll_path, GetLastError());
106
+ }
107
+
108
+ HANDLE h2 = CreateFileA(ort_path, GENERIC_READ, FILE_SHARE_READ, NULL,
109
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
110
+ if (h2 != INVALID_HANDLE_VALUE) {
111
+ LARGE_INTEGER s; GetFileSizeEx(h2, &s);
112
+ printf(" OK: onnxruntime.dll exists (%.1f MB)\n", s.QuadPart/1e6);
113
+ CloseHandle(h2);
114
+ } else {
115
+ printf(" FAIL: onnxruntime.dll not found at %s (error %lu)\n", ort_path, GetLastError());
116
+ }
117
+ }
118
+
119
+ static void test_dll_loading(const char* dll_dir) {
120
+ printf("\n=== TEST 2: DLL Loading ===\n");
121
+
122
+ SetDllDirectoryA(dll_dir);
123
+
124
+ /* Try onnxruntime first */
125
+ char ort_path[MAX_PATH];
126
+ snprintf(ort_path, sizeof(ort_path), "%s\\onnxruntime.dll", dll_dir);
127
+ HMODULE hort = LoadLibraryA(ort_path);
128
+ if (hort) {
129
+ printf(" OK: onnxruntime.dll loaded\n");
130
+ FreeLibrary(hort);
131
+ } else {
132
+ printf(" FAIL: onnxruntime.dll LoadLibrary error %lu\n", GetLastError());
133
+ }
134
+
135
+ /* Try oneocr */
136
+ char dll_path[MAX_PATH];
137
+ snprintf(dll_path, sizeof(dll_path), "%s\\oneocr.dll", dll_dir);
138
+ HMODULE hmod = LoadLibraryA(dll_path);
139
+ if (hmod) {
140
+ printf(" OK: oneocr.dll loaded\n");
141
+
142
+ /* Check exports */
143
+ const char* exports[] = {
144
+ "CreateOcrInitOptions", "CreateOcrPipeline", "RunOcrPipeline",
145
+ "ReleaseOcrResult", "ReleaseOcrPipeline", NULL
146
+ };
147
+ for (int i = 0; exports[i]; i++) {
148
+ void* fn = GetProcAddress(hmod, exports[i]);
149
+ printf(" %s %s\n", fn ? " OK:" : " FAIL:", exports[i]);
150
+ }
151
+ FreeLibrary(hmod);
152
+ } else {
153
+ printf(" FAIL: oneocr.dll LoadLibrary error %lu\n", GetLastError());
154
+ }
155
+ }
156
+
157
+ static void test_bcrypt_cfb(void) {
158
+ printf("\n=== TEST 3: bcrypt AES-256-CFB128 ===\n");
159
+
160
+ HMODULE hbcrypt = LoadLibraryA("bcrypt.dll");
161
+ if (!hbcrypt) {
162
+ printf(" FAIL: Cannot load bcrypt.dll (error %lu)\n", GetLastError());
163
+ return;
164
+ }
165
+ printf(" OK: bcrypt.dll loaded\n");
166
+
167
+ fn_BCryptOpenAlgorithmProvider pOpen = (fn_BCryptOpenAlgorithmProvider)GetProcAddress(hbcrypt, "BCryptOpenAlgorithmProvider");
168
+ fn_BCryptSetProperty pSetProp = (fn_BCryptSetProperty)GetProcAddress(hbcrypt, "BCryptSetProperty");
169
+ fn_BCryptGenerateSymmetricKey pGenKey = (fn_BCryptGenerateSymmetricKey)GetProcAddress(hbcrypt, "BCryptGenerateSymmetricKey");
170
+ fn_BCryptDecrypt pDecrypt = (fn_BCryptDecrypt)GetProcAddress(hbcrypt, "BCryptDecrypt");
171
+ fn_BCryptCloseAlgorithmProvider pClose = (fn_BCryptCloseAlgorithmProvider)GetProcAddress(hbcrypt, "BCryptCloseAlgorithmProvider");
172
+ fn_BCryptDestroyKey pDestroy = (fn_BCryptDestroyKey)GetProcAddress(hbcrypt, "BCryptDestroyKey");
173
+
174
+ if (!pOpen || !pSetProp || !pGenKey || !pDecrypt) {
175
+ printf(" FAIL: Missing bcrypt functions\n");
176
+ return;
177
+ }
178
+
179
+ /* Test 1: Open AES provider */
180
+ BCRYPT_ALG_HANDLE hAlg = NULL;
181
+ NTSTATUS status = pOpen(&hAlg, L"AES", NULL, 0);
182
+ printf(" BCryptOpenAlgorithmProvider(AES): 0x%08lx %s\n", status, status == 0 ? "OK" : "FAIL");
183
+ if (status != 0) return;
184
+
185
+ /* Test 2: Set CFB chaining mode */
186
+ wchar_t cfb[] = L"ChainingModeCFB";
187
+ status = pSetProp(hAlg, L"ChainingMode", (unsigned char*)cfb, sizeof(cfb), 0);
188
+ printf(" BCryptSetProperty(ChainingModeCFB): 0x%08lx %s\n", status, status == 0 ? "OK" : "FAIL");
189
+
190
+ if (status != 0) {
191
+ printf(" *** CFB MODE NOT SUPPORTED IN THIS WINE VERSION! ***\n");
192
+ printf(" This is likely the root cause of error 6.\n");
193
+ printf(" Trying CBC mode instead...\n");
194
+ wchar_t cbc[] = L"ChainingModeCBC";
195
+ status = pSetProp(hAlg, L"ChainingMode", (unsigned char*)cbc, sizeof(cbc), 0);
196
+ printf(" BCryptSetProperty(ChainingModeCBC): 0x%08lx %s\n", status, status == 0 ? "OK" : "FAIL");
197
+
198
+ printf(" Trying ECB mode...\n");
199
+ wchar_t ecb[] = L"ChainingModeECB";
200
+ status = pSetProp(hAlg, L"ChainingMode", (unsigned char*)ecb, sizeof(ecb), 0);
201
+ printf(" BCryptSetProperty(ChainingModeECB): 0x%08lx %s\n", status, status == 0 ? "OK" : "FAIL");
202
+
203
+ printf(" Trying GCM mode...\n");
204
+ wchar_t gcm[] = L"ChainingModeGCM";
205
+ status = pSetProp(hAlg, L"ChainingMode", (unsigned char*)gcm, sizeof(gcm), 0);
206
+ printf(" BCryptSetProperty(ChainingModeGCM): 0x%08lx %s\n", status, status == 0 ? "OK" : "FAIL");
207
+ }
208
+
209
+ if (status == 0) {
210
+ /* Test 3: Generate key with test data */
211
+ unsigned char test_key[32] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
212
+ 0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,
213
+ 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,
214
+ 0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20};
215
+ BCRYPT_KEY_HANDLE hKey = NULL;
216
+ status = pGenKey(hAlg, &hKey, NULL, 0, test_key, 32, 0);
217
+ printf(" BCryptGenerateSymmetricKey: 0x%08lx %s\n", status, status == 0 ? "OK" : "FAIL");
218
+
219
+ if (status == 0 && hKey) {
220
+ /* Test 4: Try decrypt */
221
+ unsigned char iv[16] = {0};
222
+ unsigned char ciphertext[16] = {0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,
223
+ 0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50};
224
+ unsigned char plaintext[16] = {0};
225
+ unsigned long cbResult = 0;
226
+ status = pDecrypt(hKey, ciphertext, 16, NULL, iv, 16, plaintext, 16, &cbResult, 0);
227
+ printf(" BCryptDecrypt: 0x%08lx %s (decrypted %lu bytes)\n",
228
+ status, status == 0 ? "OK" : "FAIL", cbResult);
229
+ if (hKey) pDestroy(hKey);
230
+ }
231
+ }
232
+
233
+ pClose(hAlg, 0);
234
+ FreeLibrary(hbcrypt);
235
+ }
236
+
237
+ static void test_pipeline(const char* dll_dir, const char* key_hex) {
238
+ printf("\n=== TEST 4: CreateOcrPipeline ===\n");
239
+
240
+ SetDllDirectoryA(dll_dir);
241
+
242
+ char dll_path[MAX_PATH];
243
+ snprintf(dll_path, sizeof(dll_path), "%s\\oneocr.dll", dll_dir);
244
+
245
+ HMODULE hmod = LoadLibraryA(dll_path);
246
+ if (!hmod) {
247
+ printf(" FAIL: LoadLibrary failed: %lu\n", GetLastError());
248
+ return;
249
+ }
250
+
251
+ fn_CreateOcrInitOptions pCreateInit = (fn_CreateOcrInitOptions)GetProcAddress(hmod, "CreateOcrInitOptions");
252
+ fn_OcrInitOptionsSetUseModelDelayLoad pSetDelay = (fn_OcrInitOptionsSetUseModelDelayLoad)GetProcAddress(hmod, "OcrInitOptionsSetUseModelDelayLoad");
253
+ fn_CreateOcrPipeline pCreatePipeline = (fn_CreateOcrPipeline)GetProcAddress(hmod, "CreateOcrPipeline");
254
+ fn_ReleaseOcrInitOptions pRelInit = (fn_ReleaseOcrInitOptions)GetProcAddress(hmod, "ReleaseOcrInitOptions");
255
+ fn_ReleaseOcrPipeline pRelPipeline = (fn_ReleaseOcrPipeline)GetProcAddress(hmod, "ReleaseOcrPipeline");
256
+
257
+ if (!pCreateInit || !pCreatePipeline) {
258
+ printf(" FAIL: Missing functions\n");
259
+ return;
260
+ }
261
+
262
+ /* Init options */
263
+ long long init_opts = 0;
264
+ long long res = pCreateInit(&init_opts);
265
+ printf(" CreateOcrInitOptions: %lld %s\n", res, res == 0 ? "OK" : "FAIL");
266
+
267
+ if (pSetDelay) {
268
+ /* Try with delay load = 1 (defer ONNX model loading) */
269
+ res = pSetDelay(init_opts, 1);
270
+ printf(" OcrInitOptionsSetUseModelDelayLoad(1): %lld %s\n", res, res == 0 ? "OK" : "FAIL");
271
+ }
272
+
273
+ /* Model path and key */
274
+ char model_path[MAX_PATH];
275
+ snprintf(model_path, sizeof(model_path), "%s\\oneocr.onemodel", dll_dir);
276
+ printf(" Model path: %s\n", model_path);
277
+
278
+ int key_len = strlen(key_hex) / 2;
279
+ char key[64] = {0};
280
+ for (int i = 0; i < key_len && i < 63; i++) {
281
+ sscanf(key_hex + i*2, "%2hhx", &key[i]);
282
+ }
283
+ printf(" Key length: %d bytes\n", key_len);
284
+ printf(" Key (first 8): ");
285
+ for (int i = 0; i < 8 && i < key_len; i++) printf("%02x", (unsigned char)key[i]);
286
+ printf("...\n");
287
+
288
+ /* Try pipeline creation */
289
+ long long pipeline = 0;
290
+ printf(" Calling CreateOcrPipeline...\n");
291
+ fflush(stdout);
292
+ res = pCreatePipeline(model_path, key, init_opts, &pipeline);
293
+ printf(" CreateOcrPipeline result: %lld %s\n", res, res == 0 ? "OK" : "FAIL");
294
+
295
+ if (res != 0) {
296
+ printf("\n === DIAGNOSIS ===\n");
297
+ printf(" Error code %lld from CreateOcrPipeline.\n", res);
298
+ printf(" Most likely causes:\n");
299
+ printf(" - bcrypt AES-256-CFB128 not supported in Wine (check TEST 3 above)\n");
300
+ printf(" - onnxruntime.dll initialization failed\n");
301
+ printf(" - Model file corrupted or git-lfs pointer\n");
302
+ } else {
303
+ printf(" SUCCESS! Pipeline created.\n");
304
+ pRelPipeline(pipeline);
305
+ }
306
+
307
+ pRelInit(init_opts);
308
+ FreeLibrary(hmod);
309
+ }
310
+
311
+ int main(int argc, char** argv) {
312
+ if (argc < 2) {
313
+ fprintf(stderr, "Usage: %s <dll_dir> [model_key_hex]\n", argv[0]);
314
+ return 1;
315
+ }
316
+
317
+ const char* dll_dir = argv[1];
318
+ const char* key_hex = argc > 2 ? argv[2] :
319
+ "6b6a29544774724b3e665d625b50696f772e67552b6e43407322222222222234";
320
+
321
+ printf("OneOCR Wine Debug Tool\n");
322
+ printf("DLL dir: %s\n", dll_dir);
323
+
324
+ test_file_access(dll_dir);
325
+ test_dll_loading(dll_dir);
326
+ test_bcrypt_cfb();
327
+ test_pipeline(dll_dir, key_hex);
328
+
329
+ printf("\n=== DONE ===\n");
330
+ return 0;
331
+ }
tools/oneocr_debug.exe ADDED
Binary file (74.2 kB). View file