xref: /reactos/dll/win32/tapi32/line.c (revision 1734f297)
1 /*
2  * TAPI32 line services
3  *
4  * Copyright 1999  Andreas Mohr
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 #include <string.h>
22 #include <stdlib.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wine/winternl.h"
28 #include "wingdi.h"
29 #include "winreg.h"
30 #include "winnls.h"
31 #include "winerror.h"
32 #include "objbase.h"
33 #include "tapi.h"
34 #include "wine/debug.h"
35 
36 WINE_DEFAULT_DEBUG_CHANNEL(tapi);
37 
38 /* registry keys */
39 static const char szCountrylistKey[] =
40     "Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Country List";
41 static const char szLocationsKey[] =
42     "Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Locations";
43 static const char szCardsKey[] =
44     "Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Cards";
45 
46 
47 /***********************************************************************
48  *		lineAccept (TAPI32.@)
49  */
50 DWORD WINAPI lineAccept(HCALL hCall, LPCSTR lpsUserUserInfo, DWORD dwSize)
51 {
52     FIXME("(%p, %s, %d): stub.\n", hCall, lpsUserUserInfo, dwSize);
53     return 1;
54 }
55 
56 /***********************************************************************
57  *		lineAddProviderA (TAPI32.@)
58  */
59 DWORD WINAPI lineAddProviderA(LPCSTR lpszProviderName, HWND hwndOwner, LPDWORD lpdwPermanentProviderID)
60 {
61     FIXME("(%s, %p, %p): stub.\n", lpszProviderName, hwndOwner, lpdwPermanentProviderID);
62     return LINEERR_OPERATIONFAILED;
63 }
64 
65 /***********************************************************************
66  *		lineAddProviderW (TAPI32.@)
67  */
68 DWORD WINAPI lineAddProviderW(LPCWSTR lpszProviderName, HWND hwndOwner, LPDWORD lpdwPermanentProviderID)
69 {
70     FIXME("(%s, %p, %p): stub.\n", wine_dbgstr_w(lpszProviderName), hwndOwner, lpdwPermanentProviderID);
71     return LINEERR_OPERATIONFAILED;
72 }
73 
74 /***********************************************************************
75  *		lineAddToConference (TAPI32.@)
76  */
77 DWORD WINAPI lineAddToConference(HCALL hConfCall, HCALL hConsultCall)
78 {
79     FIXME("(%p, %p): stub.\n", hConfCall, hConsultCall);
80     return 1;
81 }
82 
83 /***********************************************************************
84  *		lineAnswer (TAPI32.@)
85  */
86 DWORD WINAPI lineAnswer(HCALL hCall, LPCSTR lpsUserUserInfo, DWORD dwSize)
87 {
88     FIXME("(%p, %s, %d): stub.\n", hCall, lpsUserUserInfo, dwSize);
89     return 1;
90 }
91 
92 /***********************************************************************
93  *		lineBlindTransfer (TAPI32.@)
94  */
95 DWORD WINAPI lineBlindTransferA(HCALL hCall, LPCSTR lpszDestAddress, DWORD dwCountryCode)
96 {
97     FIXME("(%p, %s, %08x): stub.\n", hCall, lpszDestAddress, dwCountryCode);
98     return 1;
99 }
100 
101 /***********************************************************************
102  *		lineClose (TAPI32.@)
103  */
104 DWORD WINAPI lineClose(HLINE hLine)
105 {
106     FIXME("(%p): stub.\n", hLine);
107     return 0;
108 }
109 
110 /***********************************************************************
111  *		lineCompleteCall (TAPI32.@)
112  */
113 DWORD WINAPI lineCompleteCall(HCALL hCall, LPDWORD lpdwCompletionID, DWORD dwCompletionMode, DWORD dwMessageID)
114 {
115     FIXME("(%p, %p, %08x, %08x): stub.\n", hCall, lpdwCompletionID, dwCompletionMode, dwMessageID);
116     return 1;
117 }
118 
119 /***********************************************************************
120  *		lineCompleteTransfer (TAPI32.@)
121  */
122 DWORD WINAPI lineCompleteTransfer(HCALL hCall, HCALL hConsultCall, LPHCALL lphConfCall, DWORD dwTransferMode)
123 {
124     FIXME("(%p, %p, %p, %08x): stub.\n", hCall, hConsultCall, lphConfCall, dwTransferMode);
125     return 1;
126 }
127 
128 /***********************************************************************
129  *		lineConfigDialog (TAPI32.@)
130  */
131 DWORD WINAPI lineConfigDialogA(DWORD dwDeviceID, HWND hwndOwner, LPCSTR lpszDeviceClass)
132 {
133     FIXME("(%08x, %p, %s): stub.\n", dwDeviceID, hwndOwner, lpszDeviceClass);
134     return 0;
135 }
136 
137 /***********************************************************************
138  *		lineConfigDialogW (TAPI32.@)
139  */
140 DWORD WINAPI lineConfigDialogW(DWORD dwDeviceID, HWND hwndOwner, LPCWSTR lpszDeviceClass)
141 {
142     FIXME("(%08x, %p, %s): stub.\n", dwDeviceID, hwndOwner, debugstr_w(lpszDeviceClass));
143     return 0;
144 }
145 
146 /***********************************************************************
147  *		lineConfigDialogEdit (TAPI32.@)
148  */
149 DWORD WINAPI lineConfigDialogEditA(DWORD dwDeviceID, HWND hwndOwner, LPCSTR lpszDeviceClass, LPVOID const lpDeviceConfigIn, DWORD dwSize, LPVARSTRING lpDeviceConfigOut)
150 {
151     FIXME("stub.\n");
152     return 0;
153 }
154 
155 /***********************************************************************
156  *		lineConfigProvider (TAPI32.@)
157  */
158 DWORD WINAPI lineConfigProvider(HWND hwndOwner, DWORD dwPermanentProviderID)
159 {
160     FIXME("(%p, %08x): stub.\n", hwndOwner, dwPermanentProviderID);
161     return 0;
162 }
163 
164 /***********************************************************************
165  *		lineDeallocateCall (TAPI32.@)
166  */
167 DWORD WINAPI lineDeallocateCall(HCALL hCall)
168 {
169     FIXME("(%p): stub.\n", hCall);
170     return 0;
171 }
172 
173 /***********************************************************************
174  *		lineDevSpecific (TAPI32.@)
175  */
176 DWORD WINAPI lineDevSpecific(HLINE hLine, DWORD dwAddressId, HCALL hCall, LPVOID lpParams, DWORD dwSize)
177 {
178     FIXME("(%p, %08x, %p, %p, %d): stub.\n", hLine, dwAddressId, hCall, lpParams, dwSize);
179     return 1;
180 }
181 
182 /***********************************************************************
183  *		lineDevSpecificFeature (TAPI32.@)
184  */
185 DWORD WINAPI lineDevSpecificFeature(HLINE hLine, DWORD dwFeature, LPVOID lpParams, DWORD dwSize)
186 {
187     FIXME("(%p, %08x, %p, %d): stub.\n", hLine, dwFeature, lpParams, dwSize);
188     return 1;
189 }
190 
191 /***********************************************************************
192  *		lineDial (TAPI32.@)
193  */
194 DWORD WINAPI lineDialA(HCALL hCall, LPCSTR lpszDestAddress, DWORD dwCountryCode)
195 {
196     FIXME("(%p, %s, %08x): stub.\n", hCall, lpszDestAddress, dwCountryCode);
197     return 1;
198 }
199 
200 /***********************************************************************
201  *		lineDialW (TAPI32.@)
202  */
203 DWORD WINAPI lineDialW(HCALL hCall, LPCWSTR lpszDestAddress, DWORD dwCountryCode)
204 {
205     FIXME("(%p, %s, %08x): stub.\n", hCall, debugstr_w(lpszDestAddress), dwCountryCode);
206     return 1;
207 }
208 
209 /***********************************************************************
210  *		lineDrop (TAPI32.@)
211  */
212 DWORD WINAPI lineDrop(HCALL hCall, LPCSTR lpsUserUserInfo, DWORD dwSize)
213 {
214     FIXME("(%p, %s, %08x): stub.\n", hCall, lpsUserUserInfo, dwSize);
215     return 1;
216 }
217 
218 /***********************************************************************
219  *		lineForward (TAPI32.@)
220  */
221 DWORD WINAPI lineForwardA(HLINE hLine, DWORD bAllAddress, DWORD dwAddressID, LPLINEFORWARDLIST lpForwardList, DWORD dwNumRingsNoAnswer, LPHCALL lphConsultCall, LPLINECALLPARAMS lpCallParams)
222 {
223     FIXME("stub.\n");
224     return 1;
225 }
226 
227 /***********************************************************************
228  *		lineGatherDigits (TAPI32.@)
229  */
230 DWORD WINAPI lineGatherDigitsA(HCALL hCall, DWORD dwDigitModes, LPSTR lpsDigits, DWORD dwNumDigits, LPCSTR lpszTerminationDigits, DWORD dwFirstDigitTimeout, DWORD dwInterDigitTimeout)
231 {
232     FIXME("stub.\n");
233     return 0;
234 }
235 
236 /***********************************************************************
237  *		lineGenerateDigits (TAPI32.@)
238  */
239 DWORD WINAPI lineGenerateDigitsA(HCALL hCall, DWORD dwDigitModes, LPCSTR lpszDigits, DWORD dwDuration)
240 {
241     FIXME("(%p, %08x, %s, %d): stub.\n", hCall, dwDigitModes, lpszDigits, dwDuration);
242     return 0;
243 }
244 
245 /***********************************************************************
246  *		lineGenerateTone (TAPI32.@)
247  */
248 DWORD WINAPI lineGenerateTone(HCALL hCall, DWORD dwToneMode, DWORD dwDuration, DWORD dwNumTones, LPLINEGENERATETONE lpTones)
249 {
250     FIXME("(%p, %08x, %d, %d, %p): stub.\n", hCall, dwToneMode, dwDuration, dwNumTones, lpTones);
251     return 0;
252 }
253 
254 /***********************************************************************
255  *		lineGetAddressCaps (TAPI32.@)
256  */
257 DWORD WINAPI lineGetAddressCapsA(HLINEAPP hLineApp, DWORD dwDeviceID, DWORD dwAddressID, DWORD dwAPIVersion, DWORD dwExtVersion, LPLINEADDRESSCAPS lpAddressCaps)
258 {
259     FIXME("(%p, %08x, %08x, %08x, %08x, %p): stub.\n", hLineApp, dwDeviceID, dwAddressID, dwAPIVersion, dwExtVersion, lpAddressCaps);
260     return 0;
261 }
262 
263 /***********************************************************************
264  *		lineGetAddressID (TAPI32.@)
265  */
266 DWORD WINAPI lineGetAddressIDA(HLINE hLine, LPDWORD lpdwAddressID, DWORD dwAddressMode, LPCSTR lpsAddress, DWORD dwSize)
267 {
268     FIXME("%p, %p, %08x, %s, %d): stub.\n", hLine, lpdwAddressID, dwAddressMode, lpsAddress, dwSize);
269     return 0;
270 }
271 
272 /***********************************************************************
273  *		lineGetAddressStatus (TAPI32.@)
274  */
275 DWORD WINAPI lineGetAddressStatusA(HLINE hLine, DWORD dwAddressID, LPLINEADDRESSSTATUS lpAddressStatus)
276 {
277     FIXME("(%p, %08x, %p): stub.\n", hLine, dwAddressID, lpAddressStatus);
278     return 0;
279 }
280 
281 /***********************************************************************
282  *		lineGetAppPriority (TAPI32.@)
283  */
284 DWORD WINAPI lineGetAppPriorityA(LPCSTR lpszAppFilename, DWORD dwMediaMode, LPLINEEXTENSIONID const lpExtensionID, DWORD dwRequestMode, LPVARSTRING lpExtensionName, LPDWORD lpdwPriority)
285 {
286     FIXME("(%s, %08x, %p, %08x, %p, %p): stub.\n", lpszAppFilename, dwMediaMode, lpExtensionID, dwRequestMode, lpExtensionName, lpdwPriority);
287     return 0;
288 }
289 
290 /***********************************************************************
291  *		lineGetCallInfo (TAPI32.@)
292  */
293 DWORD WINAPI lineGetCallInfoA(HCALL hCall, LPLINECALLINFO lpCallInfo)
294 {
295     FIXME("(%p, %p): stub.\n", hCall, lpCallInfo);
296     return 0;
297 }
298 
299 /***********************************************************************
300  *		lineGetCallStatus (TAPI32.@)
301  */
302 DWORD WINAPI lineGetCallStatus(HCALL hCall, LPLINECALLSTATUS lpCallStatus)
303 {
304     FIXME("(%p, %p): stub.\n", hCall, lpCallStatus);
305     return 0;
306 }
307 
308 /***********************************************************************
309  *		lineGetConfRelatedCalls (TAPI32.@)
310  */
311 DWORD WINAPI lineGetConfRelatedCalls(HCALL hCall, LPLINECALLLIST lpCallList)
312 {
313     FIXME("(%p, %p): stub.\n", hCall, lpCallList);
314     return 0;
315 }
316 
317 /***********************************************************************
318  *		lineGetCountryA (TAPI32.@)
319  */
320 DWORD WINAPI lineGetCountryA(DWORD dwCountryID, DWORD dwAPIVersion, LPLINECOUNTRYLIST lpLineCountryList)
321 {
322     DWORD dwAvailSize, dwOffset, i, num_countries, max_subkey_len;
323     LPLINECOUNTRYENTRY lpLCE;
324     HKEY hkey;
325     char *subkey_name;
326 
327     if(!lpLineCountryList) {
328 	TRACE("(%08x, %08x, %p): stub. Returning LINEERR_INVALPOINTER\n",
329 	      dwCountryID, dwAPIVersion, lpLineCountryList);
330         return LINEERR_INVALPOINTER;
331     }
332 
333     TRACE("(%08x, %08x, %p(%d)): stub.\n",
334 	  dwCountryID, dwAPIVersion, lpLineCountryList,
335 	  lpLineCountryList->dwTotalSize);
336 
337     if(RegOpenKeyA(HKEY_LOCAL_MACHINE, szCountrylistKey, &hkey)
338             != ERROR_SUCCESS)
339         return LINEERR_INIFILECORRUPT;
340 
341 
342     dwAvailSize = lpLineCountryList->dwTotalSize;
343     dwOffset = sizeof (LINECOUNTRYLIST);
344 
345     if(dwAvailSize<dwOffset)
346         return LINEERR_STRUCTURETOOSMALL;
347 
348     memset(lpLineCountryList, 0, dwAvailSize);
349 
350     lpLineCountryList->dwTotalSize         = dwAvailSize;
351     lpLineCountryList->dwUsedSize          = dwOffset;
352     lpLineCountryList->dwNumCountries      = 0;
353     lpLineCountryList->dwCountryListSize   = 0;
354     lpLineCountryList->dwCountryListOffset = dwOffset;
355 
356     lpLCE = (LPLINECOUNTRYENTRY)(&lpLineCountryList[1]);
357 
358     if(RegQueryInfoKeyA(hkey, NULL, NULL, NULL, &num_countries, &max_subkey_len,
359 			NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
360         RegCloseKey(hkey);
361         return LINEERR_STRUCTURETOOSMALL;
362     }
363 
364     if(dwCountryID)
365         dwOffset = sizeof (LINECOUNTRYENTRY);
366     else
367         dwOffset += num_countries * sizeof (LINECOUNTRYENTRY);
368 
369     max_subkey_len++;
370     subkey_name = HeapAlloc(GetProcessHeap(), 0, max_subkey_len);
371     for(i = 0; i < num_countries; i++)
372     {
373         DWORD len, size, size_int, size_long, size_name, size_same;
374 	HKEY hsubkey;
375 
376 	if(RegEnumKeyA(hkey, i, subkey_name, max_subkey_len) !=
377 	   ERROR_SUCCESS)
378 	    continue;
379 
380         if(dwCountryID && (atoi(subkey_name) != dwCountryID))
381             continue;
382 
383 	if(RegOpenKeyA(hkey, subkey_name, &hsubkey) != ERROR_SUCCESS)
384 	    continue;
385 
386 	RegQueryValueExA(hsubkey, "InternationalRule", NULL, NULL,
387 			 NULL, &size_int);
388         len  = size_int;
389 
390 	RegQueryValueExA(hsubkey, "LongDistanceRule", NULL, NULL,
391 			 NULL, &size_long);
392         len += size_long;
393 
394 	RegQueryValueExA(hsubkey, "Name", NULL, NULL,
395 			 NULL, &size_name);
396         len += size_name;
397 
398 	RegQueryValueExA(hsubkey, "SameAreaRule", NULL, NULL,
399 			 NULL, &size_same);
400         len += size_same;
401 
402         if(dwAvailSize < (dwOffset+len))
403         {
404             dwOffset += len;
405 	    RegCloseKey(hsubkey);
406 	    if(dwCountryID)
407 		break;
408             continue;
409         }
410 
411         lpLineCountryList->dwNumCountries++;
412         lpLineCountryList->dwCountryListSize += sizeof (LINECOUNTRYENTRY);
413         lpLineCountryList->dwUsedSize += len + sizeof (LINECOUNTRYENTRY);
414 
415 	if(dwCountryID)
416 	    i = 0;
417 
418         lpLCE[i].dwCountryID = atoi(subkey_name);
419 	size = sizeof(DWORD);
420 	RegQueryValueExA(hsubkey, "CountryCode", NULL, NULL,
421 			 (BYTE*)&lpLCE[i].dwCountryCode, &size);
422 
423 	lpLCE[i].dwNextCountryID = 0;
424 
425 	if(i > 0)
426             lpLCE[i-1].dwNextCountryID = lpLCE[i].dwCountryID;
427 
428         /* add country name */
429         lpLCE[i].dwCountryNameSize = size_name;
430         lpLCE[i].dwCountryNameOffset = dwOffset;
431 	RegQueryValueExA(hsubkey, "Name", NULL, NULL,
432 			 ((LPBYTE)lpLineCountryList)+dwOffset,
433 			 &size_name);
434         dwOffset += size_name;
435 
436         /* add Same Area Rule */
437         lpLCE[i].dwSameAreaRuleSize = size_same;
438         lpLCE[i].dwSameAreaRuleOffset = dwOffset;
439 	RegQueryValueExA(hsubkey, "SameAreaRule", NULL, NULL,
440 			 ((LPBYTE)lpLineCountryList)+dwOffset,
441 			 &size_same);
442         dwOffset += size_same;
443 
444         /* add Long Distance Rule */
445         lpLCE[i].dwLongDistanceRuleSize = size_long;
446         lpLCE[i].dwLongDistanceRuleOffset = dwOffset;
447 	RegQueryValueExA(hsubkey, "LongDistanceRule", NULL, NULL,
448 			 ((LPBYTE)lpLineCountryList)+dwOffset,
449 			 &size_long);
450         dwOffset += size_long;
451 
452         /* add Long Distance Rule */
453         lpLCE[i].dwInternationalRuleSize = size_int;
454         lpLCE[i].dwInternationalRuleOffset = dwOffset;
455 	RegQueryValueExA(hsubkey, "InternationalRule", NULL, NULL,
456 			 ((LPBYTE)lpLineCountryList)+dwOffset,
457 			 &size_int);
458         dwOffset += size_int;
459 	RegCloseKey(hsubkey);
460 
461         TRACE("Added country %s at %p\n", (LPSTR)lpLineCountryList + lpLCE[i].dwCountryNameOffset,
462 	      &lpLCE[i]);
463 
464 	if(dwCountryID) break;
465     }
466 
467     lpLineCountryList->dwNeededSize = dwOffset;
468 
469     TRACE("%d available %d required\n", dwAvailSize, dwOffset);
470 
471     HeapFree(GetProcessHeap(), 0, subkey_name);
472     RegCloseKey(hkey);
473 
474     return 0;
475 }
476 
477 /***********************************************************************
478  *		lineGetCountryW (TAPI32.@)
479  */
480 DWORD WINAPI lineGetCountryW(DWORD id, DWORD version, LPLINECOUNTRYLIST list)
481 {
482     static const WCHAR country_listW[] =
483         {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
484          'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
485          'T','e','l','e','p','h','o','n','y','\\','C','o','u','n','t','r','y',' ','L','i','s','t',0};
486     static const WCHAR international_ruleW[] =
487         {'I','n','t','e','r','n','a','t','i','o','n','a','l','R','u','l','e',0};
488     static const WCHAR longdistance_ruleW[] =
489         {'L','o','n','g','D','i','s','t','a','n','c','e','R','u','l','e',0};
490     static const WCHAR samearea_ruleW[] =
491         {'S','a','m','e','A','r','e','a','R','u','l','e',0};
492     static const WCHAR nameW[] =
493         {'N','a','m','e',0};
494     static const WCHAR country_codeW[] =
495         {'C','o','u','n','t','r','y','C','o','d','e',0};
496     DWORD total_size, offset, i, num_countries, max_subkey_len;
497     LINECOUNTRYENTRY *entry;
498     WCHAR *subkey_name;
499     HKEY hkey;
500 
501     if (!list) return LINEERR_INVALPOINTER;
502     TRACE("(%08x, %08x, %p(%d))\n", id, version, list, list->dwTotalSize);
503 
504     if (RegOpenKeyW(HKEY_LOCAL_MACHINE, country_listW, &hkey) != ERROR_SUCCESS)
505         return LINEERR_INIFILECORRUPT;
506 
507     total_size = list->dwTotalSize;
508     offset = sizeof(LINECOUNTRYLIST);
509     if (total_size < offset) return LINEERR_STRUCTURETOOSMALL;
510 
511     memset(list, 0, total_size);
512     list->dwTotalSize         = total_size;
513     list->dwUsedSize          = offset;
514     list->dwNumCountries      = 0;
515     list->dwCountryListSize   = 0;
516     list->dwCountryListOffset = offset;
517 
518     entry = (LINECOUNTRYENTRY *)(list + 1);
519 
520     if (RegQueryInfoKeyW(hkey, NULL, NULL, NULL, &num_countries, &max_subkey_len,
521                          NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
522     {
523         RegCloseKey(hkey);
524         return LINEERR_OPERATIONFAILED;
525     }
526     if (id) offset = sizeof(LINECOUNTRYENTRY);
527     else offset += num_countries * sizeof(LINECOUNTRYENTRY);
528 
529     max_subkey_len++;
530     if (!(subkey_name = HeapAlloc(GetProcessHeap(), 0, max_subkey_len * sizeof(WCHAR))))
531     {
532         RegCloseKey(hkey);
533         return LINEERR_NOMEM;
534     }
535     for (i = 0; i < num_countries; i++)
536     {
537         DWORD len, size, size_int, size_long, size_name, size_same;
538         HKEY hsubkey;
539 
540         if (RegEnumKeyW(hkey, i, subkey_name, max_subkey_len) != ERROR_SUCCESS) continue;
541         if (id && (wcstol(subkey_name, NULL, 10) != id)) continue;
542         if (RegOpenKeyW(hkey, subkey_name, &hsubkey) != ERROR_SUCCESS) continue;
543 
544         RegQueryValueExW(hsubkey, international_ruleW, NULL, NULL, NULL, &size_int);
545         len = size_int;
546 
547         RegQueryValueExW(hsubkey, longdistance_ruleW, NULL, NULL, NULL, &size_long);
548         len += size_long;
549 
550         RegQueryValueExW(hsubkey, nameW, NULL, NULL, NULL, &size_name);
551         len += size_name;
552 
553         RegQueryValueExW(hsubkey, samearea_ruleW, NULL, NULL, NULL, &size_same);
554         len += size_same;
555 
556         if (total_size < offset + len)
557         {
558             offset += len;
559             RegCloseKey(hsubkey);
560             if (id) break;
561             continue;
562         }
563         list->dwNumCountries++;
564         list->dwCountryListSize += sizeof(LINECOUNTRYENTRY);
565         list->dwUsedSize += len + sizeof(LINECOUNTRYENTRY);
566 
567         if (id) i = 0;
568         entry[i].dwCountryID = wcstol(subkey_name, NULL, 10);
569         size = sizeof(DWORD);
570         RegQueryValueExW(hsubkey, country_codeW, NULL, NULL, (BYTE *)&entry[i].dwCountryCode, &size);
571         entry[i].dwNextCountryID = 0;
572 
573         if (i > 0) entry[i - 1].dwNextCountryID = entry[i].dwCountryID;
574 
575         /* add country name */
576         entry[i].dwCountryNameSize = size_name;
577         entry[i].dwCountryNameOffset = offset;
578         RegQueryValueExW(hsubkey, nameW, NULL, NULL, (BYTE *)list + offset, &size_name);
579         offset += size_name;
580 
581         /* add Same Area Rule */
582         entry[i].dwSameAreaRuleSize = size_same;
583         entry[i].dwSameAreaRuleOffset = offset;
584         RegQueryValueExW(hsubkey, samearea_ruleW, NULL, NULL, (BYTE *)list + offset, &size_same);
585         offset += size_same;
586 
587         /* add Long Distance Rule */
588         entry[i].dwLongDistanceRuleSize = size_long;
589         entry[i].dwLongDistanceRuleOffset = offset;
590         RegQueryValueExW(hsubkey, longdistance_ruleW, NULL, NULL, (BYTE *)list + offset, &size_long);
591         offset += size_long;
592 
593         /* add Long Distance Rule */
594         entry[i].dwInternationalRuleSize = size_int;
595         entry[i].dwInternationalRuleOffset = offset;
596         RegQueryValueExW(hsubkey, international_ruleW, NULL, NULL, (BYTE *)list + offset, &size_int);
597         offset += size_int;
598         RegCloseKey(hsubkey);
599 
600         TRACE("added country %s at %p\n",
601               debugstr_w((const WCHAR *)((const char *)list + entry[i].dwCountryNameOffset)), &entry[i]);
602         if (id) break;
603     }
604     list->dwNeededSize = offset;
605 
606     TRACE("%d available %d required\n", total_size, offset);
607 
608     HeapFree(GetProcessHeap(), 0, subkey_name);
609     RegCloseKey(hkey);
610     return 0;
611 }
612 
613 /***********************************************************************
614  *		lineGetDevCapsW (TAPI32.@)
615  */
616 DWORD WINAPI lineGetDevCapsW(HLINEAPP hLineApp, DWORD dwDeviceID, DWORD dwAPIVersion,
617                              DWORD dwExtVersion, LPLINEDEVCAPS lpLineDevCaps)
618 {
619     static int warn_once;
620 
621     if(!warn_once++)
622         FIXME("(%p, %08x, %08x, %08x, %p): stub.\n", hLineApp, dwDeviceID, dwAPIVersion,
623                                                  dwExtVersion, lpLineDevCaps);
624     return LINEERR_OPERATIONFAILED;
625 }
626 
627 /***********************************************************************
628  *		lineGetDevCapsA (TAPI32.@)
629  */
630 DWORD WINAPI lineGetDevCapsA(HLINEAPP hLineApp, DWORD dwDeviceID, DWORD dwAPIVersion,
631                              DWORD dwExtVersion, LPLINEDEVCAPS lpLineDevCaps)
632 {
633     static int warn_once;
634 
635     if(!warn_once++)
636         FIXME("(%p, %08x, %08x, %08x, %p): stub.\n", hLineApp, dwDeviceID, dwAPIVersion,
637                                                  dwExtVersion, lpLineDevCaps);
638     return LINEERR_OPERATIONFAILED;
639 }
640 
641 /***********************************************************************
642  *		lineGetDevConfig (TAPI32.@)
643  */
644 DWORD WINAPI lineGetDevConfigA(DWORD dwDeviceID, LPVARSTRING lpDeviceConfig, LPCSTR lpszDeviceClass)
645 {
646     FIXME("(%08x, %p, %s): stub.\n", dwDeviceID, lpDeviceConfig, lpszDeviceClass);
647     return 0;
648 }
649 
650 /***********************************************************************
651  *		lineGetIDW (TAPI32.@)
652  */
653 DWORD WINAPI lineGetIDW(HLINE hLine, DWORD dwAddressID, HCALL hCall, DWORD dwSelect,
654                         LPVARSTRING lpDeviceID, LPCWSTR lpszDeviceClass)
655 {
656     FIXME("(%p, %08x, %p, %08x, %p, %s): stub.\n", hLine, dwAddressID, hCall,
657                                                    dwSelect, lpDeviceID,
658                                                    debugstr_w(lpszDeviceClass));
659     return LINEERR_OPERATIONFAILED;
660 }
661 
662 /***********************************************************************
663  *		lineGetIDA (TAPI32.@)
664  */
665 DWORD WINAPI lineGetIDA(HLINE hLine, DWORD dwAddressID, HCALL hCall, DWORD dwSelect,
666                         LPVARSTRING lpDeviceID, LPCSTR lpszDeviceClass)
667 {
668     FIXME("(%p, %08x, %p, %08x, %p, %s): stub.\n", hLine, dwAddressID, hCall,
669                                                    dwSelect, lpDeviceID, lpszDeviceClass);
670     return LINEERR_OPERATIONFAILED;
671 }
672 
673 /***********************************************************************
674  *		lineGetIcon (TAPI32.@)
675  */
676 DWORD WINAPI lineGetIconA(DWORD dwDeviceID, LPCSTR lpszDeviceClass, HICON *lphIcon)
677 {
678     FIXME("(%08x, %s, %p): stub.\n", dwDeviceID, lpszDeviceClass, lphIcon);
679     return 0;
680 }
681 
682 /***********************************************************************
683  *		lineGetLineDevStatus (TAPI32.@)
684  */
685 DWORD WINAPI lineGetLineDevStatusA(HLINE hLine, LPLINEDEVSTATUS lpLineDevStatus)
686 {
687     FIXME("(%p, %p): stub.\n", hLine, lpLineDevStatus);
688     return 0;
689 }
690 
691 /***********************************************************************
692  *              lineGetMessage (TAPI32.@)
693  */
694 DWORD WINAPI lineGetMessage(HLINEAPP hLineApp, LPLINEMESSAGE lpMessage, DWORD dwTimeout)
695 {
696     FIXME("(%p, %p, %08x): stub.\n", hLineApp, lpMessage, dwTimeout);
697     return 0;
698 }
699 
700 /***********************************************************************
701  *		lineGetNewCalls (TAPI32.@)
702  */
703 DWORD WINAPI lineGetNewCalls(HLINE hLine, DWORD dwAddressID, DWORD dwSelect, LPLINECALLLIST lpCallList)
704 {
705     FIXME("(%p, %08x, %08x, %p): stub.\n", hLine, dwAddressID, dwSelect, lpCallList);
706     return 0;
707 }
708 
709 /***********************************************************************
710  *		lineGetNumRings (TAPI32.@)
711  */
712 DWORD WINAPI lineGetNumRings(HLINE hLine, DWORD dwAddressID, LPDWORD lpdwNumRings)
713 {
714     FIXME("(%p, %08x, %p): stub.\n", hLine, dwAddressID, lpdwNumRings);
715     return 0;
716 }
717 
718 /***********************************************************************
719  *		lineGetProviderListA (TAPI32.@)
720  */
721 DWORD WINAPI lineGetProviderListA(DWORD dwAPIVersion, LPLINEPROVIDERLIST lpProviderList)
722 {
723     FIXME("(%08x, %p): stub.\n", dwAPIVersion, lpProviderList);
724     return LINEERR_OPERATIONFAILED;
725 }
726 
727 /***********************************************************************
728  *		lineGetProviderListW (TAPI32.@)
729  */
730 DWORD WINAPI lineGetProviderListW(DWORD dwAPIVersion, LPLINEPROVIDERLIST lpProviderList)
731 {
732     FIXME("(%08x, %p): stub.\n", dwAPIVersion, lpProviderList);
733     return LINEERR_OPERATIONFAILED;
734 }
735 
736 /***********************************************************************
737  *		lineGetRequest (TAPI32.@)
738  */
739 DWORD WINAPI lineGetRequestA(HLINEAPP hLineApp, DWORD dwRequestMode, LPVOID lpRequestBuffer)
740 {
741     FIXME("%p, %08x, %p): stub.\n", hLineApp, dwRequestMode, lpRequestBuffer);
742     return 0;
743 }
744 
745 /***********************************************************************
746  *		lineGetStatusMessages (TAPI32.@)
747  */
748 DWORD WINAPI lineGetStatusMessages(HLINE hLine, LPDWORD lpdwLineStatus, LPDWORD lpdwAddressStates)
749 {
750     FIXME("(%p, %p, %p): stub.\n", hLine, lpdwLineStatus, lpdwAddressStates);
751     return 0;
752 }
753 
754 /***********************************************************************
755  *		lineGetTranslateCaps (TAPI32.@)
756  *
757  *      get address translate capabilities. Returns a LINETRANSLATECAPS
758  *      structure:
759  *
760  *      +-----------------------+
761  *      |TotalSize              |
762  *      |NeededSize             |
763  *      |UsedSize               |
764  *      +-----------------------+
765  *      |NumLocations           |
766  *      |LocationsListSize      |
767  *      |LocationsListOffset    | -+
768  *      |CurrentLocationID      |  |
769  *      +-----------------------+  |
770  *      |NumCards               |  |
771  *      |CardListSize           |  |
772  *      |CardListOffset         | -|--+
773  *      |CurrentPreferredCardID |  |  |
774  *      +-----------------------+  |  |
775  *      |                       | <+  |
776  *      |LINELOCATIONENTRY #1   |     |
777  *      |                       |     |
778  *      +-----------------------+     |
779  *      ~                       ~     |
780  *      +-----------------------+     |
781  *      |                       |     |
782  *      |LINELOCATIONENTRY      |     |
783  *      |          #NumLocations|     |
784  *      +-----------------------+     |
785  *      |                       | <---+
786  *      |LINECARDENTRY #1       |
787  *      |                       |
788  *      +-----------------------+
789  *      ~                       ~
790  *      +-----------------------+
791  *      |                       |
792  *      |LINECARDENTRY #NumCards|
793  *      |                       |
794  *      +-----------------------+
795  *      | room for strings named|
796  *      | in the structures     |
797  *      | above.                |
798  *      +-----------------------+
799  */
800 DWORD WINAPI lineGetTranslateCapsA(HLINEAPP hLineApp, DWORD dwAPIVersion,
801         LPLINETRANSLATECAPS lpTranslateCaps)
802 {
803     HKEY hkLocations, hkCards, hkCardLocations, hsubkey;
804     int numlocations, numcards;
805     DWORD maxlockeylen,
806         maxcardkeylen;
807     char *loc_key_name = NULL;
808     char *card_key_name = NULL;
809     LPBYTE strptr;
810     int length;
811     int i;
812     DWORD lendword;
813     DWORD currentid;
814     LPLINELOCATIONENTRY pLocEntry;
815     LPLINECARDENTRY pCardEntry;
816 
817     TRACE("(%p, %08x, %p (tot. size %d)\n", hLineApp, dwAPIVersion,
818             lpTranslateCaps, lpTranslateCaps->dwTotalSize );
819     if( lpTranslateCaps->dwTotalSize < sizeof(LINETRANSLATECAPS))
820         return LINEERR_STRUCTURETOOSMALL;
821     if( RegCreateKeyA(HKEY_LOCAL_MACHINE, szLocationsKey, &hkLocations)
822             != ERROR_SUCCESS ) {
823         ERR("unexpected registry error 1.\n");
824         return LINEERR_INIFILECORRUPT;
825     }
826     lendword = sizeof( DWORD);
827     if( RegQueryValueExA( hkLocations, "CurrentID", NULL, NULL,
828                 (LPBYTE) &currentid, &lendword) != ERROR_SUCCESS )
829         currentid = -1;  /* change this later */
830     if(RegQueryInfoKeyA(hkLocations, NULL, NULL, NULL, NULL, &maxlockeylen,
831 			NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
832         RegCloseKey(hkLocations);
833         ERR("unexpected registry error 2.\n");
834         return LINEERR_INIFILECORRUPT;
835     }
836     maxlockeylen++;
837     if( maxlockeylen < 10)
838         maxlockeylen = 10; /* need this also if there is no key */
839     loc_key_name = HeapAlloc( GetProcessHeap(), 0, maxlockeylen);
840     /* first time through: calculate needed space */
841     length=0;
842     i=0;
843     numlocations=0;
844     while( RegEnumKeyA(hkLocations, i, loc_key_name, maxlockeylen)
845             == ERROR_SUCCESS){
846         DWORD size_val;
847         i++;
848         if( _strnicmp(loc_key_name, "location", 8)  ||
849                 (RegOpenKeyA(hkLocations, loc_key_name, &hsubkey)
850                  != ERROR_SUCCESS))
851             continue;
852         numlocations++;
853         length += sizeof(LINELOCATIONENTRY);
854         RegQueryValueExA(hsubkey, "Name",NULL,NULL,NULL,&size_val);
855         length += size_val;
856         RegQueryValueExA(hsubkey, "AreaCode",NULL,NULL,NULL,&size_val);
857         length += size_val;
858         RegQueryValueExA(hsubkey, "OutsideAccess",NULL,NULL,NULL,&size_val);
859         length += size_val;
860         RegQueryValueExA(hsubkey, "LongDistanceAccess",NULL,NULL,NULL,&size_val);
861         length += size_val;
862         RegQueryValueExA(hsubkey, "DisableCallWaiting",NULL,NULL,NULL,&size_val);
863         length += size_val;
864         /* fixme: what about TollPrefixList???? */
865         RegCloseKey(hsubkey);
866     }
867     if(numlocations == 0) {
868         /* add one location */
869         if( RegCreateKeyA( hkLocations, "Location1", &hsubkey)
870                 == ERROR_SUCCESS) {
871             DWORD dwval;
872             char buf[10];
873             numlocations = 1;
874             length += sizeof(LINELOCATIONENTRY) + 20 ;
875             RegSetValueExA( hsubkey, "AreaCode", 0, REG_SZ, (const BYTE *)"010", 4);
876             GetLocaleInfoA( LOCALE_SYSTEM_DEFAULT, LOCALE_ICOUNTRY, buf, 8);
877             dwval = atoi(buf);
878             RegSetValueExA( hsubkey, "Country", 0, REG_DWORD, (LPBYTE)&dwval,
879                     sizeof(DWORD));
880             RegSetValueExA( hsubkey, "DisableCallWaiting", 0, REG_SZ, (const BYTE *)"", 1);
881             dwval = 1;
882             RegSetValueExA( hsubkey, "Flags", 0, REG_DWORD, (LPBYTE)&dwval,
883                     sizeof(DWORD));
884             RegSetValueExA( hsubkey, "LongDistanceAccess", 0, REG_SZ, (const BYTE *)"", 1);
885             RegSetValueExA( hsubkey, "Name", 0, REG_SZ, (const BYTE *)"New Location", 13);
886             RegSetValueExA( hsubkey, "OutsideAccess", 0, REG_SZ, (const BYTE *)"", 1);
887             RegCloseKey(hsubkey);
888             dwval = 1;
889             RegSetValueExA( hkLocations, "CurrentID", 0, REG_DWORD,
890                     (LPBYTE)&dwval, sizeof(DWORD));
891             dwval = 2;
892             RegSetValueExA( hkLocations, "NextID", 0, REG_DWORD, (LPBYTE)&dwval,
893                     sizeof(DWORD));
894         }
895     }
896     /* do the card list */
897     numcards=0;
898     if( RegCreateKeyA(HKEY_CURRENT_USER, szCardsKey, &hkCards)
899             == ERROR_SUCCESS ) {
900         if(RegQueryInfoKeyA(hkCards, NULL, NULL, NULL, NULL, &maxcardkeylen,
901                 NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
902             maxcardkeylen++;
903             if( maxcardkeylen < 6) maxcardkeylen = 6;
904             card_key_name = HeapAlloc(GetProcessHeap(), 0, maxcardkeylen);
905             i=0;
906             while( RegEnumKeyA(hkCards, i, card_key_name, maxcardkeylen) ==
907                     ERROR_SUCCESS){
908                 DWORD size_val;
909                 i++;
910                 if( _strnicmp(card_key_name, "card", 4)  || ERROR_SUCCESS !=
911                         (RegOpenKeyA(hkCards, card_key_name, &hsubkey) ))
912                     continue;
913                 numcards++;
914                 length += sizeof(LINECARDENTRY);
915                 RegQueryValueExA(hsubkey, "Name",NULL,NULL,NULL,&size_val);
916                 length += size_val;
917                 RegQueryValueExA(hsubkey, "LocalRule",NULL,NULL,NULL,&size_val);
918                 length += size_val;
919                 RegQueryValueExA(hsubkey, "LDRule",NULL,NULL,NULL,&size_val);
920                 length += size_val;
921                 RegQueryValueExA(hsubkey, "InternationalRule",NULL,NULL,NULL,
922                         &size_val);
923                 length += size_val;
924                 RegCloseKey(hsubkey);
925             }
926         }
927         /* add one card (direct call) */
928         if (numcards == 0 &&
929                 ERROR_SUCCESS == RegCreateKeyA( hkCards, "Card1", &hsubkey)) {
930             DWORD dwval;
931             numcards = 1;
932             length += sizeof(LINECARDENTRY) + 22 ;
933             RegSetValueExA( hsubkey, "Name", 0, REG_SZ, (const BYTE *)"None (Direct Call)", 19);
934             dwval = 1;
935             RegSetValueExA( hsubkey, "Flags", 0, REG_DWORD, (LPBYTE)&dwval,
936                     sizeof(DWORD));
937             RegSetValueExA( hsubkey, "InternationalRule", 0, REG_SZ, (const BYTE *)"", 1);
938             RegSetValueExA( hsubkey, "LDRule", 0, REG_SZ, (const BYTE *)"", 1);
939             RegSetValueExA( hsubkey, "LocalRule", 0, REG_SZ, (const BYTE *)"", 1);
940             RegCloseKey(hsubkey);
941             dwval = 2;
942             RegSetValueExA( hkCards, "NextID", 0, REG_DWORD, (LPBYTE)&dwval,
943                     sizeof(DWORD));
944         }
945     } else hkCards = 0;  /* should really fail */
946     /* check if sufficient room is available */
947     lpTranslateCaps->dwNeededSize =  sizeof(LINETRANSLATECAPS) + length;
948     if ( lpTranslateCaps->dwNeededSize > lpTranslateCaps->dwTotalSize ) {
949         RegCloseKey( hkLocations);
950         if( hkCards) RegCloseKey( hkCards);
951         HeapFree(GetProcessHeap(), 0, loc_key_name);
952         HeapFree(GetProcessHeap(), 0, card_key_name);
953         lpTranslateCaps->dwUsedSize = sizeof(LINETRANSLATECAPS);
954         TRACE("Insufficient space: total %d needed %d used %d\n",
955                 lpTranslateCaps->dwTotalSize,
956                 lpTranslateCaps->dwNeededSize,
957                 lpTranslateCaps->dwUsedSize);
958         return  0;
959     }
960     /* fill in the LINETRANSLATECAPS structure */
961     lpTranslateCaps->dwUsedSize = lpTranslateCaps->dwNeededSize;
962     lpTranslateCaps->dwNumLocations = numlocations;
963     lpTranslateCaps->dwLocationListSize = sizeof(LINELOCATIONENTRY) *
964             lpTranslateCaps->dwNumLocations;
965     lpTranslateCaps->dwLocationListOffset = sizeof(LINETRANSLATECAPS);
966     lpTranslateCaps->dwCurrentLocationID = currentid;
967     lpTranslateCaps->dwNumCards = numcards;
968     lpTranslateCaps->dwCardListSize = sizeof(LINECARDENTRY) *
969             lpTranslateCaps->dwNumCards;
970     lpTranslateCaps->dwCardListOffset = lpTranslateCaps->dwLocationListOffset +
971             lpTranslateCaps->dwLocationListSize;
972     lpTranslateCaps->dwCurrentPreferredCardID = 0;
973     /* this is where the strings will be stored */
974     strptr = ((LPBYTE) lpTranslateCaps) +
975         lpTranslateCaps->dwCardListOffset + lpTranslateCaps->dwCardListSize;
976     pLocEntry = (LPLINELOCATIONENTRY) (lpTranslateCaps + 1);
977     /* key with Preferred CardIDs */
978     if( RegOpenKeyA(HKEY_CURRENT_USER, szLocationsKey, &hkCardLocations)
979             != ERROR_SUCCESS )
980         hkCardLocations = 0;
981     /* second time through all locations */
982     i=0;
983     while(RegEnumKeyA(hkLocations, i, loc_key_name, maxlockeylen)
984             == ERROR_SUCCESS){
985         DWORD size_val;
986         i++;
987         if( _strnicmp(loc_key_name, "location", 8)  ||
988                 (RegOpenKeyA(hkLocations, loc_key_name, &hsubkey)
989                  != ERROR_SUCCESS))
990             continue;
991         size_val=sizeof(DWORD);
992         if( RegQueryValueExA(hsubkey, "ID",NULL, NULL,
993                 (LPBYTE) &(pLocEntry->dwPermanentLocationID), &size_val) !=
994                 ERROR_SUCCESS)
995             pLocEntry->dwPermanentLocationID = atoi( loc_key_name + 8);
996         size_val=2048;
997         RegQueryValueExA(hsubkey, "Name",NULL,NULL, strptr, &size_val);
998         pLocEntry->dwLocationNameSize = size_val;
999         pLocEntry->dwLocationNameOffset = strptr - (LPBYTE) lpTranslateCaps;
1000         strptr += size_val;
1001 
1002         size_val=2048;
1003         RegQueryValueExA(hsubkey, "AreaCode",NULL,NULL, strptr, &size_val);
1004         pLocEntry->dwCityCodeSize = size_val;
1005         pLocEntry->dwCityCodeOffset = strptr - (LPBYTE) lpTranslateCaps;
1006         strptr += size_val;
1007 
1008         size_val=2048;
1009         RegQueryValueExA(hsubkey, "OutsideAccess",NULL,NULL, strptr, &size_val);
1010         pLocEntry->dwLocalAccessCodeSize = size_val;
1011         pLocEntry->dwLocalAccessCodeOffset = strptr - (LPBYTE) lpTranslateCaps;
1012         strptr += size_val;
1013         size_val=2048;
1014         RegQueryValueExA(hsubkey, "LongDistanceAccess",NULL,NULL, strptr,
1015                 &size_val);
1016         pLocEntry->dwLongDistanceAccessCodeSize= size_val;
1017         pLocEntry->dwLongDistanceAccessCodeOffset= strptr -
1018             (LPBYTE) lpTranslateCaps;
1019         strptr += size_val;
1020         size_val=2048;
1021         RegQueryValueExA(hsubkey, "DisableCallWaiting",NULL,NULL, strptr,
1022                 &size_val);
1023         pLocEntry->dwCancelCallWaitingSize= size_val;
1024         pLocEntry->dwCancelCallWaitingOffset= strptr - (LPBYTE) lpTranslateCaps;
1025         strptr += size_val;
1026 
1027         pLocEntry->dwTollPrefixListSize = 0;    /* FIXME */
1028         pLocEntry->dwTollPrefixListOffset = 0;    /* FIXME */
1029 
1030         size_val=sizeof(DWORD);
1031         RegQueryValueExA(hsubkey, "Country",NULL,NULL,
1032                 (LPBYTE) &(pLocEntry->dwCountryCode), &size_val);
1033         pLocEntry->dwCountryID = pLocEntry->dwCountryCode; /* FIXME */
1034         RegQueryValueExA(hsubkey, "Flags",NULL,NULL,
1035                 (LPBYTE) &(pLocEntry->dwOptions), &size_val);
1036         RegCloseKey(hsubkey);
1037         /* get preferred cardid */
1038         pLocEntry->dwPreferredCardID = 0;
1039         if ( hkCardLocations) {
1040             size_val=sizeof(DWORD);
1041             if(RegOpenKeyA(hkCardLocations, loc_key_name, &hsubkey) ==
1042                     ERROR_SUCCESS) {
1043                 RegQueryValueExA(hsubkey, "CallingCard",NULL,NULL,
1044                         (LPBYTE) &(pLocEntry->dwPreferredCardID), &size_val);
1045                 RegCloseKey(hsubkey);
1046             }
1047 
1048         }
1049         /* make sure there is a currentID */
1050         if(currentid == -1){
1051             currentid = pLocEntry->dwPermanentLocationID;
1052             lpTranslateCaps->dwCurrentLocationID = currentid;
1053         }
1054         if(pLocEntry->dwPermanentLocationID == currentid )
1055             lpTranslateCaps->dwCurrentPreferredCardID =
1056                     pLocEntry->dwPreferredCardID;
1057         TRACE("added: ID %d %s CountryCode %d CityCode %s CardID %d "
1058                 "LocalAccess: %s LongDistanceAccess: %s CountryID %d "
1059                 "Options %d CancelCallWait %s\n",
1060                 pLocEntry->dwPermanentLocationID,
1061                 debugstr_a( (char*)lpTranslateCaps + pLocEntry->dwLocationNameOffset),
1062                 pLocEntry->dwCountryCode,
1063                 debugstr_a( (char*)lpTranslateCaps + pLocEntry->dwCityCodeOffset),
1064                 pLocEntry->dwPreferredCardID,
1065                 debugstr_a( (char*)lpTranslateCaps + pLocEntry->dwLocalAccessCodeOffset),
1066                 debugstr_a( (char*)lpTranslateCaps + pLocEntry->dwLongDistanceAccessCodeOffset),
1067                 pLocEntry->dwCountryID,
1068                 pLocEntry->dwOptions,
1069                 debugstr_a( (char*)lpTranslateCaps + pLocEntry->dwCancelCallWaitingOffset));
1070         pLocEntry++;
1071     }
1072     pCardEntry= (LPLINECARDENTRY) pLocEntry;
1073     /* do the card list */
1074     if( hkCards) {
1075         i=0;
1076         while( RegEnumKeyA(hkCards, i, card_key_name, maxcardkeylen) ==
1077                 ERROR_SUCCESS){
1078             DWORD size_val;
1079             i++;
1080             if( _strnicmp(card_key_name, "card", 4)  ||
1081                     (RegOpenKeyA(hkCards, card_key_name, &hsubkey) != ERROR_SUCCESS))
1082                 continue;
1083             size_val=sizeof(DWORD);
1084             if( RegQueryValueExA(hsubkey, "ID",NULL, NULL,
1085                     (LPBYTE) &(pCardEntry->dwPermanentCardID), &size_val) !=
1086                     ERROR_SUCCESS)
1087                 pCardEntry->dwPermanentCardID= atoi( card_key_name + 4);
1088             size_val=2048;
1089             RegQueryValueExA(hsubkey, "Name",NULL,NULL, strptr, &size_val);
1090             pCardEntry->dwCardNameSize = size_val;
1091             pCardEntry->dwCardNameOffset = strptr - (LPBYTE) lpTranslateCaps;
1092             strptr += size_val;
1093             pCardEntry->dwCardNumberDigits = 1; /* FIXME */
1094             size_val=2048;
1095             RegQueryValueExA(hsubkey, "LocalRule",NULL,NULL, strptr, &size_val);
1096             pCardEntry->dwSameAreaRuleSize= size_val;
1097             pCardEntry->dwSameAreaRuleOffset= strptr - (LPBYTE) lpTranslateCaps;
1098             strptr += size_val;
1099             size_val=2048;
1100             RegQueryValueExA(hsubkey, "LDRule",NULL,NULL, strptr, &size_val);
1101             pCardEntry->dwLongDistanceRuleSize = size_val;
1102             pCardEntry->dwLongDistanceRuleOffset = strptr - (LPBYTE) lpTranslateCaps;
1103             strptr += size_val;
1104             size_val=2048;
1105             RegQueryValueExA(hsubkey, "InternationalRule",NULL,NULL, strptr,
1106                     &size_val);
1107             pCardEntry->dwInternationalRuleSize = size_val;
1108             pCardEntry->dwInternationalRuleOffset = strptr -
1109                 (LPBYTE) lpTranslateCaps;
1110             strptr += size_val;
1111             size_val=sizeof(DWORD);
1112             RegQueryValueExA(hsubkey, "Flags",NULL, NULL,
1113                     (LPBYTE) &(pCardEntry->dwOptions), &size_val);
1114             TRACE( "added card: ID %d name %s SameArea %s LongDistance %s International %s Options 0x%x\n",
1115                     pCardEntry->dwPermanentCardID,
1116                     debugstr_a( (char*)lpTranslateCaps + pCardEntry->dwCardNameOffset),
1117                     debugstr_a( (char*)lpTranslateCaps + pCardEntry->dwSameAreaRuleOffset),
1118                     debugstr_a( (char*)lpTranslateCaps + pCardEntry->dwLongDistanceRuleOffset),
1119                     debugstr_a( (char*)lpTranslateCaps + pCardEntry->dwInternationalRuleOffset),
1120                     pCardEntry->dwOptions);
1121 
1122             pCardEntry++;
1123         }
1124     }
1125 
1126     if(hkLocations) RegCloseKey(hkLocations);
1127     if(hkCards) RegCloseKey(hkCards);
1128     if(hkCardLocations) RegCloseKey(hkCardLocations);
1129     HeapFree(GetProcessHeap(), 0, loc_key_name);
1130     HeapFree(GetProcessHeap(), 0, card_key_name);
1131     TRACE(" returning success tot %d needed %d used %d\n",
1132             lpTranslateCaps->dwTotalSize,
1133             lpTranslateCaps->dwNeededSize,
1134             lpTranslateCaps->dwUsedSize );
1135     return 0; /* success */
1136 }
1137 
1138 /***********************************************************************
1139  *		lineHandoff (TAPI32.@)
1140  */
1141 DWORD WINAPI lineHandoffA(HCALL hCall, LPCSTR lpszFileName, DWORD dwMediaMode)
1142 {
1143     FIXME("(%p, %s, %08x): stub.\n", hCall, lpszFileName, dwMediaMode);
1144     return 0;
1145 }
1146 
1147 /***********************************************************************
1148  *		lineHold (TAPI32.@)
1149  */
1150 DWORD WINAPI lineHold(HCALL hCall)
1151 {
1152     FIXME("(%p): stub.\n", hCall);
1153     return 1;
1154 }
1155 
1156 /***********************************************************************
1157  *		lineInitialize (TAPI32.@)
1158  */
1159 DWORD WINAPI lineInitialize(
1160   LPHLINEAPP lphLineApp,
1161   HINSTANCE hInstance,
1162   LINECALLBACK lpfnCallback,
1163   LPCSTR lpszAppName,
1164   LPDWORD lpdwNumDevs)
1165 {
1166     FIXME("(%p, %p, %p, %s, %p): stub.\n", lphLineApp, hInstance,
1167 	  lpfnCallback, debugstr_a(lpszAppName), lpdwNumDevs);
1168     return 0;
1169 }
1170 
1171 /***********************************************************************
1172  *              lineInitializeExA (TAPI32.@)
1173  */
1174 LONG WINAPI lineInitializeExA(LPHLINEAPP lphLineApp, HINSTANCE hInstance, LINECALLBACK lpfnCallback, LPCSTR lpszFriendlyAppName, LPDWORD lpdwNumDevs, LPDWORD lpdwAPIVersion, LPLINEINITIALIZEEXPARAMS lpLineInitializeExParams)
1175 {
1176     FIXME("(%p, %p, %p, %s, %p, %p, %p): stub.\n", lphLineApp, hInstance,
1177           lpfnCallback, debugstr_a(lpszFriendlyAppName), lpdwNumDevs, lpdwAPIVersion, lpLineInitializeExParams);
1178     return 0;
1179 }
1180 
1181 /***********************************************************************
1182  *              lineInitializeExW (TAPI32.@)
1183  */
1184 LONG WINAPI lineInitializeExW(LPHLINEAPP lphLineApp, HINSTANCE hInstance, LINECALLBACK lpfnCallback, LPCWSTR lpszFriendlyAppName, LPDWORD lpdwNumDevs, LPDWORD lpdwAPIVersion, LPLINEINITIALIZEEXPARAMS lpLineInitializeExParams)
1185 {
1186     FIXME("(%p, %p, %p, %s, %p, %p, %p): stub.\n", lphLineApp, hInstance,
1187           lpfnCallback, debugstr_w(lpszFriendlyAppName), lpdwNumDevs, lpdwAPIVersion, lpLineInitializeExParams);
1188     return 0;
1189 }
1190 
1191 /***********************************************************************
1192  *		lineMakeCallW (TAPI32.@)
1193  */
1194 DWORD WINAPI lineMakeCallW(HLINE hLine, LPHCALL lphCall, LPCWSTR lpszDestAddress,
1195                            DWORD dwCountryCode, LPLINECALLPARAMS lpCallParams)
1196 {
1197     FIXME("(%p, %p, %s, %08x, %p): stub.\n", hLine, lphCall, debugstr_w(lpszDestAddress),
1198                                              dwCountryCode, lpCallParams);
1199     return LINEERR_OPERATIONFAILED;
1200 }
1201 
1202 /***********************************************************************
1203  *		lineMakeCallA (TAPI32.@)
1204  */
1205 DWORD WINAPI lineMakeCallA(HLINE hLine, LPHCALL lphCall, LPCSTR lpszDestAddress,
1206                            DWORD dwCountryCode, LPLINECALLPARAMS lpCallParams)
1207 {
1208     FIXME("(%p, %p, %s, %08x, %p): stub.\n", hLine, lphCall, lpszDestAddress,
1209                                              dwCountryCode, lpCallParams);
1210     return LINEERR_OPERATIONFAILED;
1211 }
1212 
1213 /***********************************************************************
1214  *		lineMonitorDigits (TAPI32.@)
1215  */
1216 DWORD WINAPI lineMonitorDigits(HCALL hCall, DWORD dwDigitModes)
1217 {
1218     FIXME("(%p, %08x): stub.\n", hCall, dwDigitModes);
1219     return 0;
1220 }
1221 
1222 /***********************************************************************
1223  *		lineMonitorMedia (TAPI32.@)
1224  */
1225 DWORD WINAPI lineMonitorMedia(HCALL hCall, DWORD dwMediaModes)
1226 {
1227     FIXME("(%p, %08x): stub.\n", hCall, dwMediaModes);
1228     return 0;
1229 }
1230 
1231 /***********************************************************************
1232  *		lineMonitorTones (TAPI32.@)
1233  */
1234 DWORD WINAPI lineMonitorTones(HCALL hCall, LPLINEMONITORTONE lpToneList, DWORD dwNumEntries)
1235 {
1236     FIXME("(%p, %p, %08x): stub.\n", hCall, lpToneList, dwNumEntries);
1237     return 0;
1238 }
1239 
1240 /***********************************************************************
1241  *		lineNegotiateAPIVersion (TAPI32.@)
1242  */
1243 DWORD WINAPI lineNegotiateAPIVersion(
1244   HLINEAPP hLineApp,
1245   DWORD dwDeviceID,
1246   DWORD dwAPILowVersion,
1247   DWORD dwAPIHighVersion,
1248   LPDWORD lpdwAPIVersion,
1249   LPLINEEXTENSIONID lpExtensionID
1250 )
1251 {
1252     static int warn_once;
1253 
1254     if(!warn_once++)
1255         FIXME("(%p, %d, %d, %d, %p, %p): stub.\n", hLineApp, dwDeviceID,
1256               dwAPILowVersion, dwAPIHighVersion, lpdwAPIVersion, lpExtensionID);
1257     *lpdwAPIVersion = dwAPIHighVersion;
1258     return 0;
1259 }
1260 
1261 /***********************************************************************
1262  *		lineNegotiateExtVersion (TAPI32.@)
1263  */
1264 DWORD WINAPI lineNegotiateExtVersion(HLINEAPP hLineApp, DWORD dwDeviceID, DWORD dwAPIVersion, DWORD dwExtLowVersion, DWORD dwExtHighVersion, LPDWORD lpdwExtVersion)
1265 {
1266     FIXME("stub.\n");
1267     return 0;
1268 }
1269 
1270 /***********************************************************************
1271  *		lineOpenW (TAPI32.@)
1272  */
1273 DWORD WINAPI lineOpenW(HLINEAPP hLineApp, DWORD dwDeviceID, LPHLINE lphLine, DWORD dwAPIVersion, DWORD dwExtVersion, DWORD dwCallbackInstance, DWORD dwPrivileges, DWORD dwMediaModes, LPLINECALLPARAMS lpCallParams)
1274 {
1275     FIXME("stub.\n");
1276     return 0;
1277 }
1278 
1279 /***********************************************************************
1280  *		lineOpen (TAPI32.@)
1281  */
1282 DWORD WINAPI lineOpenA(HLINEAPP hLineApp, DWORD dwDeviceID, LPHLINE lphLine, DWORD dwAPIVersion, DWORD dwExtVersion, DWORD dwCallbackInstance, DWORD dwPrivileges, DWORD dwMediaModes, LPLINECALLPARAMS lpCallParams)
1283 {
1284     FIXME("stub.\n");
1285     return 0;
1286 }
1287 
1288 /***********************************************************************
1289  *		linePark (TAPI32.@)
1290  */
1291 DWORD WINAPI lineParkA(HCALL hCall, DWORD dwParkMode, LPCSTR lpszDirAddress, LPVARSTRING lpNonDirAddress)
1292 {
1293     FIXME("(%p, %08x, %s, %p): stub.\n", hCall, dwParkMode, lpszDirAddress, lpNonDirAddress);
1294     return 1;
1295 }
1296 
1297 /***********************************************************************
1298  *		linePickup (TAPI32.@)
1299  */
1300 DWORD WINAPI linePickupA(HLINE hLine, DWORD dwAddressID, LPHCALL lphCall, LPCSTR lpszDestAddress, LPCSTR lpszGroupID)
1301 {
1302     FIXME("(%p, %08x, %p, %s, %s): stub.\n", hLine, dwAddressID, lphCall, lpszDestAddress, lpszGroupID);
1303     return 1;
1304 }
1305 
1306 /***********************************************************************
1307  *		linePrepareAddToConference (TAPI32.@)
1308  */
1309 DWORD WINAPI linePrepareAddToConferenceA(HCALL hConfCall, LPHCALL lphConsultCall, LPLINECALLPARAMS lpCallParams)
1310 {
1311     FIXME("(%p, %p, %p): stub.\n", hConfCall, lphConsultCall, lpCallParams);
1312     return 1;
1313 }
1314 
1315 /***********************************************************************
1316  *		lineRedirect (TAPI32.@)
1317  */
1318 DWORD WINAPI lineRedirectA(
1319   HCALL hCall,
1320   LPCSTR lpszDestAddress,
1321   DWORD  dwCountryCode) {
1322 
1323   FIXME(": stub.\n");
1324   return 1;
1325 }
1326 
1327 /***********************************************************************
1328  *		lineRegisterRequestRecipient (TAPI32.@)
1329  */
1330 DWORD WINAPI lineRegisterRequestRecipient(HLINEAPP hLineApp, DWORD dwRegistrationInstance, DWORD dwRequestMode, DWORD dwEnable)
1331 {
1332     FIXME("(%p, %08x, %08x, %08x): stub.\n", hLineApp, dwRegistrationInstance, dwRequestMode, dwEnable);
1333     return 1;
1334 }
1335 
1336 /***********************************************************************
1337  *		lineReleaseUserUserInfo (TAPI32.@)
1338  */
1339 DWORD WINAPI lineReleaseUserUserInfo(HCALL hCall)
1340 {
1341     FIXME("(%p): stub.\n", hCall);
1342     return 1;
1343 }
1344 
1345 /***********************************************************************
1346  *		lineRemoveFromConference (TAPI32.@)
1347  */
1348 DWORD WINAPI lineRemoveFromConference(HCALL hCall)
1349 {
1350     FIXME("(%p): stub.\n", hCall);
1351     return 1;
1352 }
1353 
1354 /***********************************************************************
1355  *		lineRemoveProvider (TAPI32.@)
1356  */
1357 DWORD WINAPI lineRemoveProvider(DWORD dwPermanentProviderID, HWND hwndOwner)
1358 {
1359     FIXME("(%08x, %p): stub.\n", dwPermanentProviderID, hwndOwner);
1360     return 1;
1361 }
1362 
1363 /***********************************************************************
1364  *		lineSecureCall (TAPI32.@)
1365  */
1366 DWORD WINAPI lineSecureCall(HCALL hCall)
1367 {
1368     FIXME("(%p): stub.\n", hCall);
1369     return 1;
1370 }
1371 
1372 /***********************************************************************
1373  *		lineSendUserUserInfo (TAPI32.@)
1374  */
1375 DWORD WINAPI lineSendUserUserInfo(HCALL hCall, LPCSTR lpsUserUserInfo, DWORD dwSize)
1376 {
1377     FIXME("(%p, %s, %08x): stub.\n", hCall, lpsUserUserInfo, dwSize);
1378     return 1;
1379 }
1380 
1381 /***********************************************************************
1382  *		lineSetAppPriority (TAPI32.@)
1383  */
1384 DWORD WINAPI lineSetAppPriorityA(LPCSTR lpszAppFilename, DWORD dwMediaMode, LPLINEEXTENSIONID const lpExtensionID, DWORD dwRequestMode, LPCSTR lpszExtensionName, DWORD dwPriority)
1385 {
1386     FIXME("(%s, %08x, %p, %08x, %s, %08x): stub.\n", lpszAppFilename, dwMediaMode, lpExtensionID, dwRequestMode, lpszExtensionName, dwPriority);
1387     return 0;
1388 }
1389 
1390 /***********************************************************************
1391  *		lineSetAppSpecific (TAPI32.@)
1392  */
1393 DWORD WINAPI lineSetAppSpecific(HCALL hCall, DWORD dwAppSpecific)
1394 {
1395     FIXME("(%p, %08x): stub.\n", hCall, dwAppSpecific);
1396     return 0;
1397 }
1398 
1399 /***********************************************************************
1400  *		lineSetCallParams (TAPI32.@)
1401  */
1402 DWORD WINAPI lineSetCallParams(HCALL hCall, DWORD dwBearerMode, DWORD dwMinRate, DWORD dwMaxRate, LPLINEDIALPARAMS lpDialParams)
1403 {
1404     FIXME("(%p, %08x, %08x, %08x, %p): stub.\n", hCall, dwBearerMode, dwMinRate, dwMaxRate, lpDialParams);
1405     return 1;
1406 }
1407 
1408 /***********************************************************************
1409  *		lineSetCallPrivilege (TAPI32.@)
1410  */
1411 DWORD WINAPI lineSetCallPrivilege(HCALL hCall, DWORD dwCallPrivilege)
1412 {
1413     FIXME("(%p, %08x): stub.\n", hCall, dwCallPrivilege);
1414     return 0;
1415 }
1416 
1417 /***********************************************************************
1418  *		lineSetCurrentLocation (TAPI32.@)
1419  */
1420 DWORD WINAPI lineSetCurrentLocation(HLINEAPP hLineApp, DWORD dwLocation)
1421 {
1422     FIXME("(%p, %08x): stub.\n", hLineApp, dwLocation);
1423     return 0;
1424 }
1425 
1426 /***********************************************************************
1427  *		lineSetDevConfig (TAPI32.@)
1428  */
1429 DWORD WINAPI lineSetDevConfigA(DWORD dwDeviceID, LPVOID lpDeviceConfig, DWORD dwSize, LPCSTR lpszDeviceClass)
1430 {
1431     FIXME("(%08x, %p, %08x, %s): stub.\n", dwDeviceID, lpDeviceConfig, dwSize, lpszDeviceClass);
1432     return 0;
1433 }
1434 
1435 /***********************************************************************
1436  *		lineSetMediaControl (TAPI32.@)
1437  */
1438 DWORD WINAPI lineSetMediaControl(
1439 HLINE hLine,
1440 DWORD dwAddressID,
1441 HCALL hCall,
1442 DWORD dwSelect,
1443 LPLINEMEDIACONTROLDIGIT const lpDigitList,
1444 DWORD dwDigitNumEntries,
1445 LPLINEMEDIACONTROLMEDIA const lpMediaList,
1446 DWORD dwMediaNumEntries,
1447 LPLINEMEDIACONTROLTONE const lpToneList,
1448 DWORD dwToneNumEntries,
1449 LPLINEMEDIACONTROLCALLSTATE const lpCallStateList,
1450 DWORD dwCallStateNumEntries)
1451 {
1452     FIXME(": stub.\n");
1453     return 0;
1454 }
1455 
1456 /***********************************************************************
1457  *		lineSetMediaMode (TAPI32.@)
1458  */
1459 DWORD WINAPI lineSetMediaMode(HCALL hCall, DWORD dwMediaModes)
1460 {
1461     FIXME("(%p, %08x): stub.\n", hCall, dwMediaModes);
1462     return 0;
1463 }
1464 
1465 /***********************************************************************
1466  *		lineSetNumRings (TAPI32.@)
1467  */
1468 DWORD WINAPI lineSetNumRings(HLINE hLine, DWORD dwAddressID, DWORD dwNumRings)
1469 {
1470     FIXME("(%p, %08x, %08x): stub.\n", hLine, dwAddressID, dwNumRings);
1471     return 0;
1472 }
1473 
1474 /***********************************************************************
1475  *		lineSetStatusMessages (TAPI32.@)
1476  */
1477 DWORD WINAPI lineSetStatusMessages(HLINE hLine, DWORD dwLineStates, DWORD dwAddressStates)
1478 {
1479     FIXME("(%p, %08x, %08x): stub.\n", hLine, dwLineStates, dwAddressStates);
1480     return 0;
1481 }
1482 
1483 /***********************************************************************
1484  *		lineSetTerminal (TAPI32.@)
1485  */
1486 DWORD WINAPI lineSetTerminal(HLINE hLine, DWORD dwAddressID, HCALL hCall, DWORD dwSelect, DWORD dwTerminalModes, DWORD dwTerminalID, DWORD bEnable)
1487 {
1488     FIXME("(%p, %08x, %p, %08x, %08x, %08x, %08x): stub.\n", hLine, dwAddressID, hCall, dwSelect, dwTerminalModes, dwTerminalID, bEnable);
1489     return 1;
1490 }
1491 
1492 /***********************************************************************
1493  *		lineSetTollList (TAPI32.@)
1494  */
1495 DWORD WINAPI lineSetTollListA(HLINEAPP hLineApp, DWORD dwDeviceID, LPCSTR lpszAddressIn, DWORD dwTollListOption)
1496 {
1497     FIXME("(%p, %08x, %s, %08x): stub.\n", hLineApp, dwDeviceID, lpszAddressIn, dwTollListOption);
1498     return 0;
1499 }
1500 
1501 /***********************************************************************
1502  *		lineSetupConference (TAPI32.@)
1503  */
1504 DWORD WINAPI lineSetupConferenceA(HCALL hCall, HLINE hLine, LPHCALL lphConfCall, LPHCALL lphConsultCall, DWORD dwNumParties, LPLINECALLPARAMS lpCallParams)
1505 {
1506     FIXME("(%p, %p, %p, %p, %08x, %p): stub.\n", hCall, hLine, lphConfCall, lphConsultCall, dwNumParties, lpCallParams);
1507     return 1;
1508 }
1509 
1510 /***********************************************************************
1511  *		lineSetupTransfer (TAPI32.@)
1512  */
1513 DWORD WINAPI lineSetupTransferA(HCALL hCall, LPHCALL lphConsultCall, LPLINECALLPARAMS lpCallParams)
1514 {
1515     FIXME("(%p, %p, %p): stub.\n", hCall, lphConsultCall, lpCallParams);
1516     return 1;
1517 }
1518 
1519 /***********************************************************************
1520  *		lineShutdown (TAPI32.@)
1521  */
1522 DWORD WINAPI lineShutdown(HLINEAPP hLineApp)
1523 {
1524     FIXME("(%p): stub.\n", hLineApp);
1525     return 0;
1526 }
1527 
1528 /***********************************************************************
1529  *		lineSwapHold (TAPI32.@)
1530  */
1531 DWORD WINAPI lineSwapHold(HCALL hActiveCall, HCALL hHeldCall)
1532 {
1533     FIXME("(active: %p, held: %p): stub.\n", hActiveCall, hHeldCall);
1534     return 1;
1535 }
1536 
1537 /***********************************************************************
1538  *		lineTranslateAddress (TAPI32.@)
1539  */
1540 DWORD WINAPI lineTranslateAddressA(HLINEAPP hLineApp, DWORD dwDeviceID, DWORD dwAPIVersion, LPCSTR lpszAddressIn, DWORD dwCard, DWORD dwTranslateOptions, LPLINETRANSLATEOUTPUT lpTranslateOutput)
1541 {
1542     FIXME("(%p, %08x, %08x, %s, %08x, %08x, %p): stub.\n", hLineApp, dwDeviceID, dwAPIVersion, lpszAddressIn, dwCard, dwTranslateOptions, lpTranslateOutput);
1543     return 0;
1544 }
1545 
1546 /***********************************************************************
1547  *              lineTranslateAddressW (TAPI32.@)
1548  */
1549 DWORD WINAPI lineTranslateAddressW(HLINEAPP hLineApp, DWORD dwDeviceID,
1550         DWORD dwAPIVersion, LPCWSTR lpszAddressIn, DWORD dwCard,
1551         DWORD dwTranslateOptions, LPLINETRANSLATEOUTPUT lpTranslateOutput)
1552 {
1553     FIXME("(%p, %08x, %08x, %s, %08x, %08x, %p): stub.\n", hLineApp, dwDeviceID, dwAPIVersion,
1554             debugstr_w(lpszAddressIn), dwCard, dwTranslateOptions, lpTranslateOutput);
1555     return 0;
1556 }
1557 
1558 /***********************************************************************
1559  *		lineTranslateDialog (TAPI32.@)
1560  */
1561 DWORD WINAPI lineTranslateDialogA(HLINEAPP hLineApp, DWORD dwDeviceID, DWORD dwAPIVersion, HWND hwndOwner, LPCSTR lpszAddressIn)
1562 {
1563     FIXME("(%p, %08x, %08x, %p, %s): stub.\n", hLineApp, dwDeviceID, dwAPIVersion, hwndOwner, lpszAddressIn);
1564     return 0;
1565 }
1566 
1567 /***********************************************************************
1568  *              lineTranslateDialogW (TAPI32.@)
1569  */
1570 DWORD WINAPI lineTranslateDialogW(HLINEAPP hLineApp, DWORD dwDeviceID,
1571         DWORD dwAPIVersion, HWND hwndOwner, LPCWSTR lpszAddressIn)
1572 {
1573     FIXME("(%p, %08x, %08x, %p, %s): stub.\n", hLineApp, dwDeviceID,
1574             dwAPIVersion, hwndOwner, debugstr_w(lpszAddressIn));
1575     return 0;
1576 }
1577 
1578 /***********************************************************************
1579  *		lineUncompleteCall (TAPI32.@)
1580  */
1581 DWORD WINAPI lineUncompleteCall(HLINE hLine, DWORD dwCompletionID)
1582 {
1583     FIXME("(%p, %08x): stub.\n", hLine, dwCompletionID);
1584     return 1;
1585 }
1586 
1587 /***********************************************************************
1588  *		lineUnhold (TAPI32.@)
1589  */
1590 DWORD WINAPI lineUnhold(HCALL hCall)
1591 {
1592     FIXME("(%p): stub.\n", hCall);
1593     return 1;
1594 }
1595 
1596 /***********************************************************************
1597  *		lineUnpark (TAPI32.@)
1598  */
1599 DWORD WINAPI lineUnparkA(HLINE hLine, DWORD dwAddressID, LPHCALL lphCall, LPCSTR lpszDestAddress)
1600 {
1601     FIXME("(%p, %08x, %p, %s): stub.\n", hLine, dwAddressID, lphCall, lpszDestAddress);
1602     return 1;
1603 }
1604