ReactOS  0.4.14-dev-114-gc8cbd56
CShellLink.cpp
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS api tests
3  * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4  * PURPOSE: Test for CShellLink
5  * PROGRAMMER: Andreas Maier
6  */
7 
8 #include "shelltest.h"
9 
10 #define NDEBUG
11 #include <debug.h>
12 #include <stdio.h>
13 #include <shellutils.h>
14 
15 /* Test IShellLink::SetPath with environment-variables, existing, non-existing, ...*/
16 typedef struct
17 {
20 
21  /* Test 1 - hrGetPathX = IShellLink::GetPath(pathOutX, ... , flagsX); */
26 
27  /* Test 2 */
33 
35 {
36  {
37  L"%comspec%", S_OK,
38  L"%comspec%", SLGP_SHORTPATH, S_OK, TRUE,
39  L"%comspec%", SLGP_RAWPATH, S_OK, FALSE
40  },
41  {
42  L"%anyvar%", E_INVALIDARG,
43  L"", SLGP_SHORTPATH, S_FALSE, FALSE,
44  L"", SLGP_RAWPATH, S_FALSE, FALSE
45  },
46  {
47  L"%anyvar%%comspec%", S_OK,
48  L"c:\\%anyvar%%comspec%", SLGP_SHORTPATH, S_OK, TRUE,
49  L"%anyvar%%comspec%", SLGP_RAWPATH, S_OK, FALSE
50  },
51  {
52  L"%temp%", S_OK,
53  L"%temp%", SLGP_SHORTPATH, S_OK, TRUE,
54  L"%temp%", SLGP_RAWPATH, S_OK, FALSE
55  },
56  {
57  L"%shell%", S_OK,
58  L"%systemroot%\\system32\\%shell%", SLGP_SHORTPATH, S_OK, TRUE,
59  L"%shell%", SLGP_RAWPATH, S_OK, FALSE
60  },
61  {
62  L"u:\\anypath\\%anyvar%", S_OK,
63  L"u:\\anypath\\%anyvar%", SLGP_SHORTPATH, S_OK, TRUE,
64  L"u:\\anypath\\%anyvar%", SLGP_RAWPATH, S_OK, FALSE
65  },
66  {
67  L"c:\\temp", S_OK,
68  L"c:\\temp", SLGP_SHORTPATH, S_OK, FALSE,
69  L"c:\\temp", SLGP_RAWPATH, S_OK, FALSE
70  },
71  {
72  L"cmd.exe", S_OK,
73  L"%comspec%", SLGP_SHORTPATH, S_OK, TRUE,
74  L"%comspec%", SLGP_RAWPATH, S_OK, TRUE
75  },
76  {
77  L"%systemroot%\\non-existent-file", S_OK,
78  L"%systemroot%\\non-existent-file", SLGP_SHORTPATH, S_OK, TRUE,
79  L"%systemroot%\\non-existent-file", SLGP_RAWPATH, S_OK, FALSE
80  },
81  {
82  L"c:\\non-existent-path\\non-existent-file", S_OK,
83  L"c:\\non-existent-path\\non-existent-file", SLGP_SHORTPATH, S_OK, FALSE,
84  L"c:\\non-existent-path\\non-existent-file", SLGP_RAWPATH, S_OK, FALSE
85  },
86  {
87  L"non-existent-file", E_INVALIDARG,
88  L"", SLGP_SHORTPATH, S_FALSE, FALSE,
89  L"", SLGP_RAWPATH, S_FALSE, FALSE
90  },
91 };
92 
93 static
94 VOID
96 {
97 static WCHAR evVar[MAX_PATH];
98 
99  HRESULT hr, expectedHr;
100  WCHAR wPathOut[MAX_PATH];
101  BOOL expandPathOut;
102  PCWSTR expectedPathOut;
103  CComPtr<IShellLinkW> psl;
104  UINT i1;
105  DWORD flags;
106 
107  hr = CoCreateInstance(CLSID_ShellLink,
108  NULL,
109  CLSCTX_INPROC_SERVER,
110  IID_PPV_ARG(IShellLinkW, &psl));
111  ok(hr == S_OK, "CoCreateInstance, hr = 0x%lx\n", hr);
112  if (FAILED(hr))
113  {
114  skip("Could not instantiate CShellLink\n");
115  return;
116  }
117 
118  hr = psl->SetPath(testDef->pathIn);
119  ok(hr == testDef->hrSetPath, "IShellLink::SetPath(%d), got hr = 0x%lx, expected 0x%lx\n", i, hr, testDef->hrSetPath);
120 
121  expectedPathOut = NULL;
122  for (i1 = 0; i1 <= 1; i1++)
123  {
124  if (i1 == 0) /* Usually SLGP_SHORTPATH */
125  {
126  flags = testDef->flags1;
127  expandPathOut = testDef->expandPathOut1;
128  expectedPathOut = testDef->pathOut1;
129  expectedHr = testDef->hrGetPath1;
130  }
131  else // if (i1 == 1) /* Usually SLGP_RAWPATH */
132  {
133  flags = testDef->flags2;
134  expandPathOut = testDef->expandPathOut2;
135  expectedPathOut = testDef->pathOut2;
136  expectedHr = testDef->hrGetPath2;
137  }
138 
139  /* Patch some variables */
140  if (expandPathOut)
141  {
142  ExpandEnvironmentStringsW(expectedPathOut, evVar, _countof(evVar));
143  DPRINT("** %S **\n",evVar);
144  expectedPathOut = evVar;
145  }
146 
147  hr = psl->GetPath(wPathOut, _countof(wPathOut), NULL, flags);
148  ok(hr == expectedHr,
149  "IShellLink::GetPath(%d), flags 0x%lx, got hr = 0x%lx, expected 0x%lx\n",
150  i, flags, hr, expectedHr);
151  ok(wcsicmp(wPathOut, expectedPathOut) == 0,
152  "IShellLink::GetPath(%d), flags 0x%lx, in %S, got %S, expected %S\n",
153  i, flags, testDef->pathIn, wPathOut, expectedPathOut);
154  }
155 }
156 
157 static
158 VOID
160 {
161  UINT i;
162 
163  /* Needed for test */
164  SetEnvironmentVariableW(L"shell", L"cmd.exe");
165 
166  for (i = 0; i < _countof(linkTestList); ++i)
167  {
168  DPRINT("IShellLink-Test(%d): %S\n", i, linkTestList[i].pathIn);
170  }
171 
173 }
174 
175 static
176 VOID
178 {
179  HRESULT hr;
180  CComPtr<IShellLinkW> psl;
181  WCHAR buffer[64];
182  PCWSTR testDescription = L"This is a test description";
183 
184  /* Test SetDescription */
185  hr = CoCreateInstance(CLSID_ShellLink,
186  NULL,
187  CLSCTX_INPROC_SERVER,
188  IID_PPV_ARG(IShellLinkW, &psl));
189  ok(hr == S_OK, "CoCreateInstance, hr = 0x%lx\n", hr);
190  if (FAILED(hr))
191  {
192  skip("Could not instantiate CShellLink\n");
193  return;
194  }
195 
196  memset(buffer, 0x55, sizeof(buffer));
197  hr = psl->GetDescription(buffer, RTL_NUMBER_OF(buffer));
198  ok(hr == S_OK, "IShellLink::GetDescription returned hr = 0x%lx\n", hr);
199  ok(buffer[0] == 0, "buffer[0] = %x\n", buffer[0]);
200  ok(buffer[1] == 0x5555, "buffer[1] = %x\n", buffer[1]);
201 
202  hr = psl->SetDescription(testDescription);
203  ok(hr == S_OK, "IShellLink::SetDescription returned hr = 0x%lx\n", hr);
204 
205  memset(buffer, 0x55, sizeof(buffer));
206  hr = psl->GetDescription(buffer, RTL_NUMBER_OF(buffer));
207  ok(hr == S_OK, "IShellLink::GetDescription returned hr = 0x%lx\n", hr);
208  ok(buffer[wcslen(testDescription)] == 0, "buffer[n] = %x\n", buffer[wcslen(testDescription)]);
209  ok(buffer[wcslen(testDescription) + 1] == 0x5555, "buffer[n+1] = %x\n", buffer[wcslen(testDescription) + 1]);
210  ok(!wcscmp(buffer, testDescription), "buffer = '%ls'\n", buffer);
211 
212  hr = psl->SetDescription(NULL);
213  ok(hr == S_OK, "IShellLink::SetDescription returned hr = 0x%lx\n", hr);
214 
215  memset(buffer, 0x55, sizeof(buffer));
216  hr = psl->GetDescription(buffer, RTL_NUMBER_OF(buffer));
217  ok(hr == S_OK, "IShellLink::GetDescription returned hr = 0x%lx\n", hr);
218  ok(buffer[0] == 0, "buffer[0] = %x\n", buffer[0]);
219  ok(buffer[1] == 0x5555, "buffer[1] = %x\n", buffer[1]);
220 }
221 
222 
223 /* Test IShellLink::Get/SetIconLocation and IExtractIcon::GetIconLocation */
224 typedef struct
225 {
227 
228  /* Expected results */
229  HRESULT hrDefIcon; // Return value for GIL_DEFAULTICON
230  HRESULT hrForShrt; // Return value for GIL_FORSHORTCUT
231  /* Return values for GIL_FORSHELL */
236 
238 {
239  /* Executable with icons */
240  {L"%SystemRoot%\\system32\\cmd.exe", S_FALSE, E_INVALIDARG,
241  S_OK, L"%SystemRoot%\\system32\\cmd.exe", GIL_NOTFILENAME | GIL_PERINSTANCE},
242 
243  /* Executable without icon */
244  {L"%SystemRoot%\\system32\\autochk.exe", S_FALSE, E_INVALIDARG,
245  S_OK, L"%SystemRoot%\\system32\\autochk.exe", GIL_NOTFILENAME | GIL_PERINSTANCE},
246 
247  /* Existing file */
248  {L"%SystemRoot%\\system32\\shell32.dll", S_FALSE, E_INVALIDARG,
249  S_OK, L"*", GIL_NOTFILENAME | GIL_PERCLASS},
250 
251  /* Non-existing files */
252  {L"%SystemRoot%\\non-existent-file.sdf", S_FALSE, E_INVALIDARG,
253  S_OK, L"*", GIL_NOTFILENAME | GIL_PERCLASS},
254  {L"c:\\non-existent-path\\non-existent-file.sdf", S_FALSE, E_INVALIDARG,
255  S_OK, L"*", GIL_NOTFILENAME | GIL_PERCLASS},
256 };
257 
258 static
259 VOID
261 {
262  HRESULT hr;
263  CComPtr<IShellLinkW> psl;
264  CComPtr<IExtractIconW> pei;
265  INT iIcon;
266  UINT wFlags;
267  PCWSTR pszExplorer = L"%SystemRoot%\\explorer.exe";
269  WCHAR szPath2[MAX_PATH];
270 
271  hr = CoCreateInstance(CLSID_ShellLink,
272  NULL,
273  CLSCTX_INPROC_SERVER,
274  IID_PPV_ARG(IShellLinkW, &psl));
275  ok(hr == S_OK, "CoCreateInstance, hr = 0x%lx\n", hr);
276  if (FAILED(hr))
277  {
278  skip("Could not instantiate CShellLink\n");
279  return;
280  }
281 
282  /* Set the path to a file */
284  hr = psl->SetPath(szPath);
285  ok(hr == S_OK, "IShellLink::SetPath failed, hr = 0x%lx\n", hr);
286 
287  /*
288  * This test shows that this does not imply that the icon is automatically
289  * set and be retrieved naively by a call to IShellLink::GetIconLocation.
290  */
291  iIcon = 0xdeadbeef;
292  wcscpy(szPath, L"garbage");
293  hr = psl->GetIconLocation(szPath, _countof(szPath), &iIcon);
294  ok(hr == S_OK, "IShellLink::GetIconLocation(%d) failed, hr = 0x%lx\n", i, hr);
295  ok(*szPath == L'\0', "IShellLink::GetIconLocation(%d) returned '%S'\n", i, szPath);
296  ok(iIcon == 0, "IShellLink::GetIconLocation(%d) returned %d, expected %d\n", i, iIcon, 0);
297 
298  /* Try to grab the IExtractIconW interface */
299  hr = psl->QueryInterface(IID_PPV_ARG(IExtractIconW, &pei));
300  ok(hr == S_OK, "IShellLink::QueryInterface(IExtractIconW)(%d) failed, hr = 0x%lx\n", i, hr);
301  if (!pei)
302  {
303  win_skip("No IExtractIconW interface\n");
304  return;
305  }
306 
307  iIcon = wFlags = 0xdeadbeef;
308  wcscpy(szPath, L"garbage");
309  hr = pei->GetIconLocation(GIL_DEFAULTICON, szPath, _countof(szPath), &iIcon, &wFlags);
310  ok(hr == testDef->hrDefIcon, "IExtractIcon::GetIconLocation(%d) returned hr = 0x%lx, expected 0x%lx\n", i, hr, testDef->hrDefIcon);
311  ok(*szPath == L'\0', "IExtractIcon::GetIconLocation(%d) returned '%S'\n", i, szPath);
312  // ok(iIcon == 0, "IExtractIcon::GetIconLocation(%d) returned %d\n", i, iIcon);
313 
314  iIcon = wFlags = 0xdeadbeef;
315  wcscpy(szPath, L"garbage");
316  hr = pei->GetIconLocation(GIL_FORSHORTCUT, szPath, _countof(szPath), &iIcon, &wFlags);
317  ok(hr == testDef->hrForShrt, "IExtractIcon::GetIconLocation(%d) returned hr = 0x%lx, expected 0x%lx\n", i, hr, testDef->hrForShrt);
318  // Here, both szPath and iIcon are untouched...
319 
320  iIcon = wFlags = 0xdeadbeef;
321  wcscpy(szPath, L"garbage");
322  hr = pei->GetIconLocation(GIL_FORSHELL, szPath, _countof(szPath), &iIcon, &wFlags);
323  ok(hr == testDef->hrForShell, "IExtractIcon::GetIconLocation(%d) returned hr = 0x%lx, expected 0x%lx\n", i, hr, testDef->hrForShell);
324  ok(wFlags == testDef->Flags, "IExtractIcon::GetIconLocation(%d) returned wFlags = 0x%x, expected 0x%x\n", i, wFlags, testDef->Flags);
325  /*
326  * Actually, even if wFlags specifies GIL_NOTFILENAME, a correct file name is returned
327  * for executables only (at least...), otherwise we can get an asterix '*'.
328  */
329  ExpandEnvironmentStringsW(testDef->IconPath, szPath2, _countof(szPath2));
330  ok(_wcsicmp(szPath2, szPath) == 0, "IExtractIcon::GetIconLocation(%d) returned '%S', expected '%S'\n", i, szPath, szPath2);
331 
332  // ok(*szPath == L'\0', "IExtractIcon::GetIconLocation returned '%S'\n", szPath);
333  // ok(iIcon == 0, "IExtractIcon::GetIconLocation returned %d\n", iIcon);
334  // ok(FALSE, "hr = 0x%lx, szPath = '%S', iIcon = %d, wFlags = %d\n", hr, szPath, iIcon, wFlags);
335 
336 
337  /*
338  * Now we test what happens when we explicitly set an icon to the shortcut.
339  * Note that actually, SetIconLocation() does not verify whether the file
340  * really exists.
341  */
342  hr = psl->SetIconLocation(pszExplorer, 1);
343  ok(hr == S_OK, "IShellLink::SetIconLocation(%d) failed, hr = 0x%lx\n", i, hr);
344 
345  /*
346  * First, we call IShellLink::GetIconLocation. We retrieve
347  * exactly what we specified with SetIconLocation.
348  */
349  iIcon = 0xdeadbeef;
350  wcscpy(szPath, L"garbage");
351  hr = psl->GetIconLocation(szPath, _countof(szPath), &iIcon);
352  ok(hr == S_OK, "IShellLink::GetIconLocation(%d) failed, hr = 0x%lx\n", i, hr);
353  ok(wcscmp(szPath, pszExplorer) == 0, "IShellLink::GetIconLocation(%d) returned '%S', expected '%S'\n", i, szPath, pszExplorer);
354  ok(iIcon == 1, "IShellLink::GetIconLocation(%d) returned %d, expected %d\n", i, iIcon, 1);
355 
356  /*
357  * Now we test what happens with IExtractIcon::GetIconLocation.
358  * We see that it retrieves the icon of the shortcut's underlying file.
359  */
360  iIcon = wFlags = 0xdeadbeef;
361  wcscpy(szPath, L"garbage");
362  hr = pei->GetIconLocation(GIL_DEFAULTICON, szPath, _countof(szPath), &iIcon, &wFlags);
363  ok(hr == testDef->hrDefIcon, "IExtractIcon::GetIconLocation(%d) returned hr = 0x%lx, expected 0x%lx\n", i, hr, testDef->hrDefIcon);
364  ok(*szPath == L'\0', "IExtractIcon::GetIconLocation(%d) returned '%S'\n", i, szPath);
365  // ok(iIcon == 0, "IExtractIcon::GetIconLocation(%d) returned %d\n", i, iIcon);
366 
367  iIcon = wFlags = 0xdeadbeef;
368  wcscpy(szPath, L"garbage");
369  hr = pei->GetIconLocation(GIL_FORSHORTCUT, szPath, _countof(szPath), &iIcon, &wFlags);
370  ok(hr == testDef->hrForShrt, "IExtractIcon::GetIconLocation(%d) returned hr = 0x%lx, expected 0x%lx\n", i, hr, testDef->hrForShrt);
371  // Here, both szPath and iIcon are untouched...
372 
373  iIcon = wFlags = 0xdeadbeef;
374  wcscpy(szPath, L"garbage");
375  hr = pei->GetIconLocation(GIL_FORSHELL, szPath, _countof(szPath), &iIcon, &wFlags);
376  ok(hr == testDef->hrForShell, "IExtractIcon::GetIconLocation(%d) returned hr = 0x%lx, expected 0x%lx\n", i, hr, testDef->hrForShell);
377  ok(wFlags == testDef->Flags, "IExtractIcon::GetIconLocation(%d) returned wFlags = 0x%x, expected 0x%x\n", i, wFlags, testDef->Flags);
378  /*
379  * Actually, even if wFlags specifies GIL_NOTFILENAME, a correct file name is returned
380  * for executables only (at least...), otherwise we can get an asterix '*'.
381  */
382  ExpandEnvironmentStringsW(testDef->IconPath, szPath2, _countof(szPath2));
383  ok(_wcsicmp(szPath2, szPath) == 0, "IExtractIcon::GetIconLocation(%d) returned '%S', expected '%S'\n", i, szPath, szPath2);
384 
385  // ok(*szPath == L'\0', "IExtractIcon::GetIconLocation returned '%S'\n", szPath);
386  // ok(iIcon == 0, "IExtractIcon::GetIconLocation returned %d\n", iIcon);
387  // ok(FALSE, "hr = 0x%lx, szPath = '%S', iIcon = %d, wFlags = %d\n", hr, szPath, iIcon, wFlags);
388 }
389 
390 static
391 VOID
393 {
394  UINT i;
395 
396  for (i = 0; i < _countof(ShIconTests); ++i)
397  {
399  }
400 }
401 
402 
404 {
406 
407  TestShellLink();
408  TestDescription();
410 
411  CoUninitialize();
412 }
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define TRUE
Definition: types.h:120
HRESULT hr
Definition: shlfolder.c:183
#define _countof(array)
Definition: fontsub.cpp:30
HRESULT hrForShell
Definition: CShellLink.cpp:232
GLuint buffer
Definition: glext.h:5915
#define IID_PPV_ARG(Itype, ppType)
int32_t INT
Definition: typedefs.h:56
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned int BOOL
Definition: ntddk_ex.h:94
#define S_FALSE
Definition: winerror.h:2357
#define E_INVALIDARG
Definition: ddrawi.h:101
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
__wchar_t WCHAR
Definition: xmlstorage.h:180
LONG HRESULT
Definition: typedefs.h:77
#define MAX_PATH
Definition: compat.h:26
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableW(IN LPCWSTR lpName, IN LPCWSTR lpValue)
Definition: environ.c:259
GLbitfield flags
Definition: glext.h:7161
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
static const WCHAR L[]
Definition: oid.c:1250
#define wcsicmp
Definition: string.h:1152
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3234
_In_ DWORD _Out_ _In_ WORD wFlags
Definition: wincon.h:519
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define S_OK
Definition: intsafe.h:59
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
LPCWSTR szPath
Definition: env.c:35
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:1991
#define ok(value,...)
Definition: atltest.h:57
HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
Definition: compobj.c:1935
unsigned int UINT
Definition: ndis.h:50
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
#define skip(...)
Definition: atltest.h:64
#define memset(x, y, z)
Definition: compat.h:39
#define win_skip
Definition: test.h:141
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)