2 * Copyright 2011 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/test.h"
29 DEFINE_GUID(GUID_NULL
,0,0,0,0,0,0,0,0,0,0,0);
31 #define EXPECT_HR(hr,hr_exp) \
32 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
34 static void test_wshshell(void)
36 static const WCHAR notepadW
[] = {'n','o','t','e','p','a','d','.','e','x','e',0};
37 static const WCHAR desktopW
[] = {'D','e','s','k','t','o','p',0};
38 static const WCHAR lnk1W
[] = {'f','i','l','e','.','l','n','k',0};
39 static const WCHAR pathW
[] = {'%','P','A','T','H','%',0};
40 static const WCHAR sysW
[] = {'S','Y','S','T','E','M',0};
41 static const WCHAR path2W
[] = {'P','A','T','H',0};
42 static const WCHAR dummydirW
[] = {'d','e','a','d','p','a','r','r','o','t',0};
43 static const WCHAR emptyW
[] = {'e','m','p','t','y',0};
49 IDispatch
*disp
, *shortcut
;
50 IUnknown
*shell
, *unk
;
51 IFolderCollection
*folders
;
58 VARIANT arg
, res
, arg2
;
63 hr
= CoCreateInstance(&CLSID_WshShell
, NULL
, CLSCTX_INPROC_SERVER
|CLSCTX_INPROC_HANDLER
,
64 &IID_IDispatch
, (void**)&disp
);
65 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
67 hr
= IDispatch_QueryInterface(disp
, &IID_IWshShell3
, (void**)&shell
);
69 IDispatch_Release(disp
);
71 hr
= IDispatch_QueryInterface(disp
, &IID_IDispatchEx
, (void**)&dispex
);
72 EXPECT_HR(hr
, E_NOINTERFACE
);
74 hr
= IUnknown_QueryInterface(shell
, &IID_IWshShell3
, (void**)&sh3
);
77 hr
= IWshShell3_QueryInterface(sh3
, &IID_IObjectWithSite
, (void**)&unk
);
78 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
80 hr
= IWshShell3_QueryInterface(sh3
, &IID_IWshShell
, (void**)&unk
);
81 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
82 IUnknown_Release(unk
);
84 hr
= IWshShell3_QueryInterface(sh3
, &IID_IWshShell2
, (void**)&unk
);
85 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
86 IUnknown_Release(unk
);
88 hr
= IWshShell3_get_SpecialFolders(sh3
, &coll
);
91 hr
= IWshCollection_QueryInterface(coll
, &IID_IFolderCollection
, (void**)&folders
);
92 EXPECT_HR(hr
, E_NOINTERFACE
);
94 hr
= IWshCollection_QueryInterface(coll
, &IID_IDispatch
, (void**)&disp
);
97 hr
= IDispatch_GetTypeInfo(disp
, 0, 0, &ti
);
100 hr
= ITypeInfo_GetTypeAttr(ti
, &tattr
);
102 ok(IsEqualIID(&tattr
->guid
, &IID_IWshCollection
), "got wrong type guid\n");
103 ITypeInfo_ReleaseTypeAttr(ti
, tattr
);
105 /* try to call Item() with normal IDispatch procedure */
106 str
= SysAllocString(desktopW
);
107 V_VT(&arg
) = VT_BSTR
;
110 dp
.rgdispidNamedArgs
= NULL
;
113 hr
= IDispatch_Invoke(disp
, DISPID_VALUE
, &IID_NULL
, 1033, DISPATCH_PROPERTYGET
, &dp
, &res
, &ei
, &err
);
114 EXPECT_HR(hr
, DISP_E_MEMBERNOTFOUND
);
116 /* try Item() directly, it returns directory path apparently */
117 V_VT(&res
) = VT_EMPTY
;
118 hr
= IWshCollection_Item(coll
, &arg
, &res
);
120 ok(V_VT(&res
) == VT_BSTR
, "got res type %d\n", V_VT(&res
));
124 /* CreateShortcut() */
125 str
= SysAllocString(lnk1W
);
126 hr
= IWshShell3_CreateShortcut(sh3
, str
, &shortcut
);
129 hr
= IDispatch_QueryInterface(shortcut
, &IID_IWshShortcut
, (void**)&shcut
);
132 hr
= IWshShortcut_get_Arguments(shcut
, NULL
);
133 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
135 hr
= IWshShortcut_get_IconLocation(shcut
, NULL
);
136 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
138 IWshShortcut_Release(shcut
);
139 IDispatch_Release(shortcut
);
141 /* ExpandEnvironmentStrings */
142 hr
= IWshShell3_ExpandEnvironmentStrings(sh3
, NULL
, NULL
);
143 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
145 str
= SysAllocString(pathW
);
146 hr
= IWshShell3_ExpandEnvironmentStrings(sh3
, str
, NULL
);
147 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
150 V_VT(&arg
) = VT_BSTR
;
151 V_BSTR(&arg
) = SysAllocString(sysW
);
152 hr
= IWshShell3_get_Environment(sh3
, &arg
, &env
);
153 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
156 hr
= IWshEnvironment_get_Item(env
, NULL
, NULL
);
157 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
160 hr
= IWshEnvironment_get_Item(env
, NULL
, &ret
);
161 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
162 ok(ret
&& !*ret
, "got %p\n", ret
);
165 /* invalid var name */
166 str
= SysAllocString(lnk1W
);
167 hr
= IWshEnvironment_get_Item(env
, str
, NULL
);
168 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
171 hr
= IWshEnvironment_get_Item(env
, str
, &ret
);
172 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
173 ok(ret
&& *ret
== 0, "got %s\n", wine_dbgstr_w(ret
));
178 str
= SysAllocString(path2W
);
179 hr
= IWshEnvironment_get_Item(env
, str
, &ret
);
180 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
181 ok(ret
&& *ret
!= 0, "got %s\n", wine_dbgstr_w(ret
));
185 IWshEnvironment_Release(env
);
189 V_VT(&arg2
) = VT_ERROR
;
190 V_ERROR(&arg2
) = DISP_E_PARAMNOTFOUND
;
192 str
= SysAllocString(notepadW
);
193 hr
= IWshShell3_Run(sh3
, str
, &arg
, &arg2
, NULL
);
194 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
197 hr
= IWshShell3_Run(sh3
, str
, NULL
, &arg2
, &retval
);
198 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
199 ok(retval
== 10, "got %u\n", retval
);
202 hr
= IWshShell3_Run(sh3
, str
, &arg
, NULL
, &retval
);
203 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
204 ok(retval
== 10, "got %u\n", retval
);
207 V_VT(&arg2
) = VT_ERROR
;
209 hr
= IWshShell3_Run(sh3
, str
, &arg
, &arg2
, &retval
);
210 ok(hr
== DISP_E_TYPEMISMATCH
, "got 0x%08x\n", hr
);
211 ok(retval
== 10, "got %u\n", retval
);
215 /* current directory */
216 if (0) /* crashes on native */
217 hr
= IWshShell3_get_CurrentDirectory(sh3
, NULL
);
220 hr
= IWshShell3_get_CurrentDirectory(sh3
, &str
);
221 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
222 ok(str
&& str
[0] != 0, "got empty string\n");
225 hr
= IWshShell3_put_CurrentDirectory(sh3
, NULL
);
226 ok(hr
== E_INVALIDARG
||
227 broken(hr
== HRESULT_FROM_WIN32(ERROR_NOACCESS
)), "got 0x%08x\n", hr
);
229 str
= SysAllocString(emptyW
);
230 hr
= IWshShell3_put_CurrentDirectory(sh3
, str
);
231 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "got 0x%08x\n", hr
);
234 str
= SysAllocString(dummydirW
);
235 hr
= IWshShell3_put_CurrentDirectory(sh3
, str
);
236 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "got 0x%08x\n", hr
);
240 hr
= IWshShell3_Exec(sh3
, NULL
, NULL
);
241 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
243 hr
= IWshShell3_Exec(sh3
, NULL
, &shexec
);
244 ok(hr
== DISP_E_EXCEPTION
, "got 0x%08x\n", hr
);
246 str
= SysAllocString(emptyW
);
247 hr
= IWshShell3_Exec(sh3
, str
, &shexec
);
248 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "got 0x%08x\n", hr
);
251 IWshCollection_Release(coll
);
252 IDispatch_Release(disp
);
253 IWshShell3_Release(sh3
);
254 IUnknown_Release(shell
);
257 /* delete key and all its subkeys */
258 static DWORD
delete_key(HKEY hkey
)
263 while (!(ret
= RegEnumKeyA(hkey
, 0, name
, sizeof(name
)))) {
265 if (!(ret
= RegOpenKeyExA(hkey
, name
, 0, KEY_ENUMERATE_SUB_KEYS
, &tmp
))) {
266 ret
= delete_key(tmp
);
271 if (ret
!= ERROR_NO_MORE_ITEMS
) return ret
;
272 RegDeleteKeyA(hkey
, "");
276 static void test_registry(void)
278 static const WCHAR keypathW
[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','\\',
279 'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','T','e','s','t','\\',0};
280 static const WCHAR regsz2W
[] = {'r','e','g','s','z','2',0};
281 static const WCHAR regszW
[] = {'r','e','g','s','z',0};
282 static const WCHAR regdwordW
[] = {'r','e','g','d','w','o','r','d',0};
283 static const WCHAR regbinaryW
[] = {'r','e','g','b','i','n','a','r','y',0};
284 static const WCHAR regmultiszW
[] = {'r','e','g','m','u','l','t','i','s','z',0};
286 static const WCHAR regsz1W
[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','\\',
287 'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','T','e','s','t','\\','r','e','g','s','z','1',0};
288 static const WCHAR foobarW
[] = {'f','o','o','b','a','r',0};
289 static const WCHAR fooW
[] = {'f','o','o',0};
290 static const WCHAR brokenW
[] = {'H','K','E','Y','_','b','r','o','k','e','n','_','k','e','y',0};
291 static const WCHAR broken2W
[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','a',0};
292 WCHAR pathW
[MAX_PATH
];
304 hr
= CoCreateInstance(&CLSID_WshShell
, NULL
, CLSCTX_INPROC_SERVER
|CLSCTX_INPROC_HANDLER
,
305 &IID_IWshShell3
, (void**)&sh3
);
306 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
309 V_VT(&value
) = VT_I2
;
310 hr
= IWshShell3_RegRead(sh3
, NULL
, &value
);
311 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
312 ok(V_VT(&value
) == VT_I2
, "got %d\n", V_VT(&value
));
314 name
= SysAllocString(brokenW
);
315 hr
= IWshShell3_RegRead(sh3
, name
, NULL
);
316 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
317 V_VT(&value
) = VT_I2
;
318 hr
= IWshShell3_RegRead(sh3
, name
, &value
);
319 ok(hr
== HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
), "got 0x%08x\n", hr
);
320 ok(V_VT(&value
) == VT_I2
, "got %d\n", V_VT(&value
));
323 name
= SysAllocString(broken2W
);
324 V_VT(&value
) = VT_I2
;
325 hr
= IWshShell3_RegRead(sh3
, name
, &value
);
326 ok(hr
== HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
), "got 0x%08x\n", hr
);
327 ok(V_VT(&value
) == VT_I2
, "got %d\n", V_VT(&value
));
330 ret
= RegCreateKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Test", &root
);
331 ok(ret
== 0, "got %d\n", ret
);
333 ret
= RegSetValueExA(root
, "regsz", 0, REG_SZ
, (const BYTE
*)"foobar", 7);
334 ok(ret
== 0, "got %d\n", ret
);
336 ret
= RegSetValueExA(root
, "regsz2", 0, REG_SZ
, (const BYTE
*)"foobar\0f", 9);
337 ok(ret
== 0, "got %d\n", ret
);
339 ret
= RegSetValueExA(root
, "regmultisz", 0, REG_MULTI_SZ
, (const BYTE
*)"foo\0bar\0", 9);
340 ok(ret
== 0, "got %d\n", ret
);
343 ret
= RegSetValueExA(root
, "regdword", 0, REG_DWORD
, (const BYTE
*)&dwvalue
, sizeof(dwvalue
));
344 ok(ret
== 0, "got %d\n", ret
);
347 ret
= RegSetValueExA(root
, "regbinary", 0, REG_BINARY
, (const BYTE
*)&dwvalue
, sizeof(dwvalue
));
348 ok(ret
== 0, "got %d\n", ret
);
351 lstrcpyW(pathW
, keypathW
);
352 lstrcatW(pathW
, regszW
);
353 name
= SysAllocString(pathW
);
355 hr
= IWshShell3_RegRead(sh3
, name
, &value
);
356 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
357 ok(V_VT(&value
) == VT_BSTR
, "got %d\n", V_VT(&value
));
358 ok(!lstrcmpW(V_BSTR(&value
), foobarW
), "got %s\n", wine_dbgstr_w(V_BSTR(&value
)));
359 VariantClear(&value
);
362 /* REG_SZ with embedded NULL */
363 lstrcpyW(pathW
, keypathW
);
364 lstrcatW(pathW
, regsz2W
);
365 name
= SysAllocString(pathW
);
367 hr
= IWshShell3_RegRead(sh3
, name
, &value
);
368 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
369 ok(V_VT(&value
) == VT_BSTR
, "got %d\n", V_VT(&value
));
370 ok(SysStringLen(V_BSTR(&value
)) == 6, "len %d\n", SysStringLen(V_BSTR(&value
)));
371 VariantClear(&value
);
375 lstrcpyW(pathW
, keypathW
);
376 lstrcatW(pathW
, regdwordW
);
377 name
= SysAllocString(pathW
);
379 hr
= IWshShell3_RegRead(sh3
, name
, &value
);
380 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
381 ok(V_VT(&value
) == VT_I4
, "got %d\n", V_VT(&value
));
382 ok(V_I4(&value
) == 10, "got %d\n", V_I4(&value
));
386 lstrcpyW(pathW
, keypathW
);
387 lstrcatW(pathW
, regbinaryW
);
388 name
= SysAllocString(pathW
);
390 hr
= IWshShell3_RegRead(sh3
, name
, &value
);
391 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
392 ok(V_VT(&value
) == (VT_ARRAY
|VT_VARIANT
), "got 0x%x\n", V_VT(&value
));
393 dim
= SafeArrayGetDim(V_ARRAY(&value
));
394 ok(dim
== 1, "got %u\n", dim
);
396 hr
= SafeArrayGetLBound(V_ARRAY(&value
), 1, &bound
);
397 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
398 ok(bound
== 0, "got %u\n", bound
);
400 hr
= SafeArrayGetUBound(V_ARRAY(&value
), 1, &bound
);
401 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
402 ok(bound
== 3, "got %u\n", bound
);
404 hr
= SafeArrayGetVartype(V_ARRAY(&value
), &vartype
);
405 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
406 ok(vartype
== VT_VARIANT
, "got %d\n", vartype
);
409 hr
= SafeArrayGetElement(V_ARRAY(&value
), &bound
, &v
);
410 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
411 ok(V_VT(&v
) == VT_UI1
, "got %d\n", V_VT(&v
));
412 ok(V_UI1(&v
) == 11, "got %u\n", V_UI1(&v
));
414 VariantClear(&value
);
418 lstrcpyW(pathW
, keypathW
);
419 lstrcatW(pathW
, regmultiszW
);
420 name
= SysAllocString(pathW
);
422 hr
= IWshShell3_RegRead(sh3
, name
, &value
);
423 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
424 ok(V_VT(&value
) == (VT_ARRAY
|VT_VARIANT
), "got 0x%x\n", V_VT(&value
));
427 dim
= SafeArrayGetDim(V_ARRAY(&value
));
428 ok(dim
== 1, "got %u\n", dim
);
430 hr
= SafeArrayGetLBound(V_ARRAY(&value
), 1, &bound
);
431 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
432 ok(bound
== 0, "got %u\n", bound
);
434 hr
= SafeArrayGetUBound(V_ARRAY(&value
), 1, &bound
);
435 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
436 ok(bound
== 1, "got %u\n", bound
);
438 hr
= SafeArrayGetVartype(V_ARRAY(&value
), &vartype
);
439 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
440 ok(vartype
== VT_VARIANT
, "got %d\n", vartype
);
443 hr
= SafeArrayGetElement(V_ARRAY(&value
), &bound
, &v
);
444 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
445 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
446 ok(!lstrcmpW(V_BSTR(&v
), fooW
), "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
448 VariantClear(&value
);
450 name
= SysAllocString(regsz1W
);
451 V_VT(&value
) = VT_I2
;
452 hr
= IWshShell3_RegRead(sh3
, name
, &value
);
453 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "got 0x%08x\n", hr
);
454 ok(V_VT(&value
) == VT_I2
, "got %d\n", V_VT(&value
));
455 VariantClear(&value
);
461 ret
= RegCreateKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Test", &root
);
462 ok(ret
== 0, "got %d\n", ret
);
464 hr
= IWshShell3_RegWrite(sh3
, NULL
, NULL
, NULL
);
465 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
467 lstrcpyW(pathW
, keypathW
);
468 lstrcatW(pathW
, regszW
);
469 name
= SysAllocString(pathW
);
471 hr
= IWshShell3_RegWrite(sh3
, name
, NULL
, NULL
);
472 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
475 hr
= IWshShell3_RegWrite(sh3
, name
, &value
, NULL
);
476 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
478 hr
= IWshShell3_RegWrite(sh3
, name
, &value
, &value
);
479 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
481 /* type is optional */
483 V_ERROR(&v
) = DISP_E_PARAMNOTFOUND
;
484 hr
= IWshShell3_RegWrite(sh3
, name
, &value
, &v
);
485 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
487 /* default type is REG_SZ */
488 V_VT(&value
) = VT_I4
;
490 hr
= IWshShell3_RegWrite(sh3
, name
, &value
, &v
);
491 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
494 ret
= RegQueryValueExA(root
, "regsz", 0, &type
, NULL
, NULL
);
495 ok(ret
== ERROR_SUCCESS
, "got %d\n", ret
);
496 ok(type
== REG_SZ
, "got %d\n", type
);
498 ret
= RegDeleteValueA(root
, "regsz");
499 ok(ret
== ERROR_SUCCESS
, "got %d\n", ret
);
500 V_VT(&value
) = VT_BSTR
;
501 V_BSTR(&value
) = SysAllocString(regszW
);
502 hr
= IWshShell3_RegWrite(sh3
, name
, &value
, &v
);
503 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
504 VariantClear(&value
);
507 ret
= RegQueryValueExA(root
, "regsz", 0, &type
, NULL
, NULL
);
508 ok(ret
== ERROR_SUCCESS
, "got %d\n", ret
);
509 ok(type
== REG_SZ
, "got %d\n", type
);
511 ret
= RegDeleteValueA(root
, "regsz");
512 ok(ret
== ERROR_SUCCESS
, "got %d\n", ret
);
513 V_VT(&value
) = VT_R4
;
515 hr
= IWshShell3_RegWrite(sh3
, name
, &value
, &v
);
516 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
517 VariantClear(&value
);
520 ret
= RegQueryValueExA(root
, "regsz", 0, &type
, NULL
, NULL
);
521 ok(ret
== ERROR_SUCCESS
, "got %d\n", ret
);
522 ok(type
== REG_SZ
, "got %d\n", type
);
524 ret
= RegDeleteValueA(root
, "regsz");
525 ok(ret
== ERROR_SUCCESS
, "got %d\n", ret
);
526 V_VT(&value
) = VT_R4
;
530 hr
= IWshShell3_RegWrite(sh3
, name
, &value
, &v
);
531 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
532 VariantClear(&value
);
537 IWshShell3_Release(sh3
);
547 hr
= CoCreateInstance(&CLSID_WshShell
, NULL
, CLSCTX_INPROC_SERVER
|CLSCTX_INPROC_HANDLER
,
548 &IID_IUnknown
, (void**)&unk
);
550 win_skip("Could not create WshShell object: %08x\n", hr
);
553 IUnknown_Release(unk
);