windowscodecs: Silence fixme for IID_CMetaBitmapRenderTarget.
[wine.git] / dlls / kernel32 / comm.c
blobf63be7270cf01d29b978831a6e80297c6cee5a90
1 /*
2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <stdio.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winternl.h"
28 #include "winnls.h"
29 #include "winerror.h"
30 #include "winioctl.h"
31 #include "ddk/ntddser.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(comm);
37 /***********************************************************************
38 * COMM_Parse* (Internal)
40 * The following COMM_Parse* functions are used by the BuildCommDCB
41 * functions to help parse the various parts of the device control string.
43 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
45 /* The device control string may optionally start with "COMx" followed
46 by an optional ':' and spaces. */
47 if(!wcsnicmp(ptr, L"COM", 3))
49 ptr += 3;
51 /* Allow any com port above 0 as Win 9x does (NT only allows
52 values for com ports which are actually present) */
53 if(*ptr < '1' || *ptr > '9')
54 return NULL;
56 /* Advance pointer past port number */
57 while(*ptr >= '0' && *ptr <= '9') ptr++;
59 /* The com port number must be followed by a ':' or ' ' */
60 if(*ptr != ':' && *ptr != ' ')
61 return NULL;
63 /* Advance pointer to beginning of next parameter */
64 while(*ptr == ' ') ptr++;
65 if(*ptr == ':')
67 ptr++;
68 while(*ptr == ' ') ptr++;
71 /* The device control string must not start with a space. */
72 else if(*ptr == ' ')
73 return NULL;
75 return ptr;
78 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
80 if(*ptr < '0' || *ptr > '9') return NULL;
81 *lpnumber = wcstoul(ptr, NULL, 10);
82 while(*ptr >= '0' && *ptr <= '9') ptr++;
83 return ptr;
86 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
88 /* Contrary to what you might expect, Windows only sets the Parity
89 member of DCB and not fParity even when parity is specified in the
90 device control string */
92 switch(*ptr++)
94 case 'e':
95 case 'E':
96 *lpparity = EVENPARITY;
97 break;
98 case 'm':
99 case 'M':
100 *lpparity = MARKPARITY;
101 break;
102 case 'n':
103 case 'N':
104 *lpparity = NOPARITY;
105 break;
106 case 'o':
107 case 'O':
108 *lpparity = ODDPARITY;
109 break;
110 case 's':
111 case 'S':
112 *lpparity = SPACEPARITY;
113 break;
114 default:
115 return NULL;
118 return ptr;
121 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
123 DWORD temp;
125 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
126 return NULL;
128 if(temp >= 5 && temp <= 8)
130 *lpbytesize = temp;
131 return ptr;
133 else
134 return NULL;
137 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
139 DWORD temp;
141 if(!wcsncmp(L"1.5", ptr, 3))
143 ptr += 3;
144 *lpstopbits = ONE5STOPBITS;
146 else
148 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
149 return NULL;
151 if(temp == 1)
152 *lpstopbits = ONESTOPBIT;
153 else if(temp == 2)
154 *lpstopbits = TWOSTOPBITS;
155 else
156 return NULL;
159 return ptr;
162 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
164 if(!wcsnicmp(L"on", ptr, 2))
166 ptr += 2;
167 *lponoff = 1;
169 else if(!wcsnicmp(L"off", ptr, 3))
171 ptr += 3;
172 *lponoff = 0;
174 else
175 return NULL;
177 return ptr;
180 /***********************************************************************
181 * COMM_BuildOldCommDCB (Internal)
183 * Build a DCB using the old style settings string eg: "96,n,8,1"
185 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
187 WCHAR last = 0;
189 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
190 return FALSE;
192 switch(lpdcb->BaudRate)
194 case 11:
195 case 30:
196 case 60:
197 lpdcb->BaudRate *= 10;
198 break;
199 case 12:
200 case 24:
201 case 48:
202 case 96:
203 lpdcb->BaudRate *= 100;
204 break;
205 case 19:
206 lpdcb->BaudRate = 19200;
207 break;
210 while(*device == ' ') device++;
211 if(*device++ != ',') return FALSE;
212 while(*device == ' ') device++;
214 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
215 return FALSE;
217 while(*device == ' ') device++;
218 if(*device++ != ',') return FALSE;
219 while(*device == ' ') device++;
221 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
222 return FALSE;
224 while(*device == ' ') device++;
225 if(*device++ != ',') return FALSE;
226 while(*device == ' ') device++;
228 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
229 return FALSE;
231 /* The last parameter for flow control is optional. */
232 while(*device == ' ') device++;
233 if(*device == ',')
235 device++;
236 while(*device == ' ') device++;
237 if(*device) last = *device++;
238 while(*device == ' ') device++;
241 /* Win NT sets the flow control members based on (or lack of) the last
242 parameter. Win 9x does not set these members. */
243 switch(last)
245 case 0:
246 lpdcb->fInX = FALSE;
247 lpdcb->fOutX = FALSE;
248 lpdcb->fOutxCtsFlow = FALSE;
249 lpdcb->fOutxDsrFlow = FALSE;
250 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
251 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
252 break;
253 case 'x':
254 case 'X':
255 lpdcb->fInX = TRUE;
256 lpdcb->fOutX = TRUE;
257 lpdcb->fOutxCtsFlow = FALSE;
258 lpdcb->fOutxDsrFlow = FALSE;
259 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
260 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
261 break;
262 case 'p':
263 case 'P':
264 lpdcb->fInX = FALSE;
265 lpdcb->fOutX = FALSE;
266 lpdcb->fOutxCtsFlow = TRUE;
267 lpdcb->fOutxDsrFlow = TRUE;
268 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
269 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
270 break;
271 default:
272 return FALSE;
275 /* This should be the end of the string. */
276 if(*device) return FALSE;
278 return TRUE;
281 /***********************************************************************
282 * COMM_BuildNewCommDCB (Internal)
284 * Build a DCB using the new style settings string.
285 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
287 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
289 DWORD temp;
290 BOOL baud = FALSE, stop = FALSE;
292 while(*device)
294 while(*device == ' ') device++;
296 if(!wcsnicmp(L"baud=", device, 5))
298 baud = TRUE;
300 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
301 return FALSE;
303 else if(!wcsnicmp(L"parity=", device, 7))
305 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
306 return FALSE;
308 else if(!wcsnicmp(L"data=", device, 5))
310 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
311 return FALSE;
313 else if(!wcsnicmp(L"stop=", device, 5))
315 stop = TRUE;
317 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
318 return FALSE;
320 else if(!wcsnicmp(L"to=", device, 3))
322 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
323 return FALSE;
325 lptimeouts->ReadIntervalTimeout = 0;
326 lptimeouts->ReadTotalTimeoutMultiplier = 0;
327 lptimeouts->ReadTotalTimeoutConstant = 0;
328 lptimeouts->WriteTotalTimeoutMultiplier = 0;
329 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
331 else if(!wcsnicmp(L"xon=", device, 4))
333 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
334 return FALSE;
336 lpdcb->fOutX = temp;
337 lpdcb->fInX = temp;
339 else if(!wcsnicmp(L"odsr=", device, 5))
341 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
342 return FALSE;
344 lpdcb->fOutxDsrFlow = temp;
346 else if(!wcsnicmp(L"octs=", device, 5))
348 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
349 return FALSE;
351 lpdcb->fOutxCtsFlow = temp;
353 else if(!wcsnicmp(L"dtr=", device, 4))
355 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
356 return FALSE;
358 lpdcb->fDtrControl = temp;
360 else if(!wcsnicmp(L"rts=", device, 4))
362 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
363 return FALSE;
365 lpdcb->fRtsControl = temp;
367 else if(!wcsnicmp(L"idsr=", device, 5))
369 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
370 return FALSE;
372 /* Win NT sets the fDsrSensitivity member based on the
373 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
374 lpdcb->fDsrSensitivity = temp;
376 else
377 return FALSE;
379 /* After the above parsing, the next character (if not the end of
380 the string) should be a space */
381 if(*device && *device != ' ')
382 return FALSE;
385 /* If stop bits were not specified, a default is always supplied. */
386 if(!stop)
388 if(baud && lpdcb->BaudRate == 110)
389 lpdcb->StopBits = TWOSTOPBITS;
390 else
391 lpdcb->StopBits = ONESTOPBIT;
394 return TRUE;
397 /**************************************************************************
398 * BuildCommDCBA (KERNEL32.@)
400 * Updates a device control block data structure with values from an
401 * ANSI device control string. The device control string has two forms
402 * normal and extended, it must be exclusively in one or the other form.
404 * RETURNS
406 * True on success, false on a malformed control string.
408 BOOL WINAPI BuildCommDCBA(
409 LPCSTR device, /* [in] The ANSI device control string used to update the DCB. */
410 LPDCB lpdcb) /* [out] The device control block to be updated. */
412 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
415 /**************************************************************************
416 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
418 * Updates a device control block data structure with values from an
419 * ANSI device control string. Taking timeout values from a timeouts
420 * struct if desired by the control string.
422 * RETURNS
424 * True on success, false bad handles etc.
426 BOOL WINAPI BuildCommDCBAndTimeoutsA(
427 LPCSTR device, /* [in] The ANSI device control string. */
428 LPDCB lpdcb, /* [out] The device control block to be updated. */
429 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
431 BOOL ret = FALSE;
432 UNICODE_STRING deviceW;
434 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
435 if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
436 else deviceW.Buffer = NULL;
438 if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
440 RtlFreeUnicodeString(&deviceW);
441 return ret;
444 /**************************************************************************
445 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
447 * Updates a device control block data structure with values from a
448 * unicode device control string. Taking timeout values from a timeouts
449 * struct if desired by the control string.
451 * RETURNS
453 * True on success, false bad handles etc
455 BOOL WINAPI BuildCommDCBAndTimeoutsW(
456 LPCWSTR devid, /* [in] The unicode device control string. */
457 LPDCB lpdcb, /* [out] The device control block to be updated. */
458 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
460 DCB dcb;
461 COMMTIMEOUTS timeouts;
462 BOOL result;
463 LPCWSTR ptr = devid;
465 TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
467 memset(&timeouts, 0, sizeof timeouts);
469 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
470 lpdcb->DCBlength = sizeof(DCB);
472 /* Make a copy of the original data structures to work with since if
473 if there is an error in the device control string the originals
474 should not be modified (except possibly DCBlength) */
475 dcb = *lpdcb;
476 if(lptimeouts) timeouts = *lptimeouts;
478 ptr = COMM_ParseStart(ptr);
480 if(ptr == NULL)
481 result = FALSE;
482 else if(wcschr(ptr, ','))
483 result = COMM_BuildOldCommDCB(ptr, &dcb);
484 else
485 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
487 if(result)
489 *lpdcb = dcb;
490 if(lptimeouts) *lptimeouts = timeouts;
491 return TRUE;
493 else
495 WARN("Invalid device control string: %s\n", debugstr_w(devid));
496 SetLastError(ERROR_INVALID_PARAMETER);
497 return FALSE;
501 /**************************************************************************
502 * BuildCommDCBW (KERNEL32.@)
504 * Updates a device control block structure with values from an
505 * unicode device control string. The device control string has two forms
506 * normal and extended, it must be exclusively in one or the other form.
508 * RETURNS
510 * True on success, false on a malformed control string.
512 BOOL WINAPI BuildCommDCBW(
513 LPCWSTR devid, /* [in] The unicode device control string. */
514 LPDCB lpdcb) /* [out] The device control block to be updated. */
516 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
519 /***********************************************************************
520 * FIXME:
521 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
522 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
523 * This is dependent on the type of COMM port, but since it is doubtful
524 * anybody will get around to implementing support for fancy serial
525 * ports in WINE, this is hardcoded for the time being. The name of
526 * this DLL should be stored in and read from the system registry in
527 * the hive HKEY_LOCAL_MACHINE, key
528 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
529 * where ???? is the port number... that is determined by PNP
530 * The DLL should be loaded when the COMM port is opened, and closed
531 * when the COMM port is closed. - MJM 20 June 2000
532 ***********************************************************************/
533 static const WCHAR lpszSerialUI[] = L"serialui.dll";
536 /***********************************************************************
537 * CommConfigDialogA (KERNEL32.@)
539 * Raises a dialog that allows the user to configure a comm port.
540 * Fills the COMMCONFIG struct with information specified by the user.
541 * This function should call a similar routine in the COMM driver...
543 * RETURNS
545 * TRUE on success, FALSE on failure
546 * If successful, the lpCommConfig structure will contain a new
547 * configuration for the comm port, as specified by the user.
549 * BUGS
550 * The library with the CommConfigDialog code is never unloaded.
551 * Perhaps this should be done when the comm port is closed?
553 BOOL WINAPI CommConfigDialogA(
554 LPCSTR lpszDevice, /* [in] name of communications device */
555 HWND hWnd, /* [in] parent window for the dialog */
556 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
558 LPWSTR lpDeviceW = NULL;
559 DWORD len;
560 BOOL r;
562 TRACE("(%s, %p, %p)\n", debugstr_a(lpszDevice), hWnd, lpCommConfig);
564 if (lpszDevice)
566 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
567 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
568 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
570 r = CommConfigDialogW(lpDeviceW, hWnd, lpCommConfig);
571 HeapFree( GetProcessHeap(), 0, lpDeviceW );
572 return r;
575 /***********************************************************************
576 * CommConfigDialogW (KERNEL32.@)
578 * See CommConfigDialogA.
580 BOOL WINAPI CommConfigDialogW(
581 LPCWSTR lpszDevice, /* [in] name of communications device */
582 HWND hWnd, /* [in] parent window for the dialog */
583 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
585 DWORD (WINAPI *pCommConfigDialog)(LPCWSTR, HWND, LPCOMMCONFIG);
586 HMODULE hConfigModule;
587 DWORD res = ERROR_INVALID_PARAMETER;
589 TRACE("(%s, %p, %p)\n", debugstr_w(lpszDevice), hWnd, lpCommConfig);
590 hConfigModule = LoadLibraryW(lpszSerialUI);
592 if (hConfigModule) {
593 pCommConfigDialog = (void *)GetProcAddress(hConfigModule, "drvCommConfigDialogW");
594 if (pCommConfigDialog) {
595 res = pCommConfigDialog(lpszDevice, hWnd, lpCommConfig);
597 FreeLibrary(hConfigModule);
600 if (res) SetLastError(res);
601 return (res == ERROR_SUCCESS);
604 /***********************************************************************
605 * SetDefaultCommConfigW (KERNEL32.@)
607 * Initializes the default configuration for a communication device.
609 * PARAMS
610 * lpszDevice [I] Name of the device targeted for configuration
611 * lpCommConfig [I] PTR to a buffer with the configuration for the device
612 * dwSize [I] Number of bytes in the buffer
614 * RETURNS
615 * Failure: FALSE
616 * Success: TRUE, and default configuration saved
619 BOOL WINAPI SetDefaultCommConfigW(LPCWSTR lpszDevice, LPCOMMCONFIG lpCommConfig, DWORD dwSize)
621 BOOL (WINAPI *lpfnSetDefaultCommConfig)(LPCWSTR, LPCOMMCONFIG, DWORD);
622 HMODULE hConfigModule;
623 BOOL r = FALSE;
625 TRACE("(%s, %p, %lu)\n", debugstr_w(lpszDevice), lpCommConfig, dwSize);
627 hConfigModule = LoadLibraryW(lpszSerialUI);
628 if(!hConfigModule)
629 return r;
631 lpfnSetDefaultCommConfig = (void *)GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
632 if (lpfnSetDefaultCommConfig)
633 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
635 FreeLibrary(hConfigModule);
637 return r;
641 /***********************************************************************
642 * SetDefaultCommConfigA (KERNEL32.@)
644 * Initializes the default configuration for a communication device.
646 * See SetDefaultCommConfigW.
649 BOOL WINAPI SetDefaultCommConfigA(LPCSTR lpszDevice, LPCOMMCONFIG lpCommConfig, DWORD dwSize)
651 BOOL r;
652 LPWSTR lpDeviceW = NULL;
653 DWORD len;
655 TRACE("(%s, %p, %lu)\n", debugstr_a(lpszDevice), lpCommConfig, dwSize);
657 if (lpszDevice)
659 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
660 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
661 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
663 r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
664 HeapFree( GetProcessHeap(), 0, lpDeviceW );
665 return r;
669 /***********************************************************************
670 * GetDefaultCommConfigW (KERNEL32.@)
672 * Acquires the default configuration of the specified communication device. (unicode)
674 * RETURNS
676 * True on successful reading of the default configuration,
677 * if the device is not found or the buffer is too small.
679 BOOL WINAPI GetDefaultCommConfigW(
680 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
681 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
682 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
683 afterwards the number of bytes copied to the buffer or
684 the needed size of the buffer. */
686 DWORD (WINAPI *pGetDefaultCommConfig)(LPCWSTR, LPCOMMCONFIG, LPDWORD);
687 HMODULE hConfigModule;
688 DWORD res = ERROR_INVALID_PARAMETER;
690 TRACE("(%s, %p, %p) *lpdwSize: %lu\n", debugstr_w(lpszName), lpCC, lpdwSize, lpdwSize ? *lpdwSize : 0 );
691 hConfigModule = LoadLibraryW(lpszSerialUI);
693 if (hConfigModule) {
694 pGetDefaultCommConfig = (void *)GetProcAddress(hConfigModule, "drvGetDefaultCommConfigW");
695 if (pGetDefaultCommConfig) {
696 res = pGetDefaultCommConfig(lpszName, lpCC, lpdwSize);
698 FreeLibrary(hConfigModule);
701 if (res) SetLastError(res);
702 return (res == ERROR_SUCCESS);
705 /**************************************************************************
706 * GetDefaultCommConfigA (KERNEL32.@)
708 * Acquires the default configuration of the specified communication device.
710 * RETURNS
712 * True on successful reading of the default configuration,
713 * if the device is not found or the buffer is too small.
715 BOOL WINAPI GetDefaultCommConfigA(
716 LPCSTR lpszName, /* [in] The ANSI name of the device targeted for configuration. */
717 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
718 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
719 afterwards the number of bytes copied to the buffer or
720 the needed size of the buffer. */
722 BOOL ret = FALSE;
723 UNICODE_STRING lpszNameW;
725 TRACE("(%s, %p, %p) *lpdwSize: %lu\n", debugstr_a(lpszName), lpCC, lpdwSize, lpdwSize ? *lpdwSize : 0 );
726 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
727 else lpszNameW.Buffer = NULL;
729 ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
731 RtlFreeUnicodeString(&lpszNameW);
732 return ret;