[KERNEL32]
[reactos.git] / reactos / dll / win32 / kernel32 / client / vista.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * PURPOSE: Vista functions
5 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
6 */
7
8 /* INCLUDES *******************************************************************/
9
10 #include <k32.h>
11
12 #define NDEBUG
13 #include <debug.h>
14
15 #if _WIN32_WINNT >= 0x600
16
17 /* FIXME: Move these RTL declarations to the NDK */
18 NTSTATUS
19 NTAPI
20 RtlSleepConditionVariableCS(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable,
21 IN OUT PRTL_CRITICAL_SECTION CriticalSection,
22 IN PLARGE_INTEGER TimeOut OPTIONAL);
23
24 NTSTATUS
25 NTAPI
26 RtlSleepConditionVariableSRW(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable,
27 IN OUT PRTL_SRWLOCK SRWLock,
28 IN PLARGE_INTEGER TimeOut OPTIONAL,
29 IN ULONG Flags);
30
31 /* PUBLIC FUNCTIONS ***********************************************************/
32
33 /*
34 * @implemented
35 */
36 BOOL
37 WINAPI
38 SleepConditionVariableCS(IN OUT PCONDITION_VARIABLE ConditionVariable,
39 IN OUT PCRITICAL_SECTION CriticalSection,
40 IN DWORD dwMilliseconds)
41 {
42 NTSTATUS Status = 0;
43 LARGE_INTEGER TimeOut;
44 PLARGE_INTEGER TimeOutPtr = NULL;
45
46 if (dwMilliseconds != INFINITE)
47 {
48 TimeOut.QuadPart = dwMilliseconds * -10000LL;
49 TimeOutPtr = &TimeOut;
50 }
51
52 #if 0
53 Status = RtlSleepConditionVariableCS((PRTL_CONDITION_VARIABLE)ConditionVariable,
54 (PRTL_CRITICAL_SECTION)CriticalSection,
55 TimeOutPtr);
56 #endif
57 if (!NT_SUCCESS(Status))
58 {
59 BaseSetLastNTError(Status);
60 return FALSE;
61 }
62
63 return TRUE;
64 }
65
66
67 /*
68 * @implemented
69 */
70 BOOL
71 WINAPI
72 SleepConditionVariableSRW(IN OUT PCONDITION_VARIABLE ConditionVariable,
73 IN OUT PSRWLOCK SRWLock,
74 IN DWORD dwMilliseconds,
75 IN ULONG Flags)
76 {
77 NTSTATUS Status = 0;
78 LARGE_INTEGER TimeOut;
79 PLARGE_INTEGER TimeOutPtr = NULL;
80
81 if (dwMilliseconds != INFINITE)
82 {
83 TimeOut.QuadPart = dwMilliseconds * -10000LL;
84 TimeOutPtr = &TimeOut;
85 }
86
87 #if 0
88 Status = RtlSleepConditionVariableSRW((PRTL_CONDITION_VARIABLE)ConditionVariable,
89 (PRTL_SRWLOCK)SRWLock,
90 TimeOutPtr,
91 Flags);
92 #endif
93 if (!NT_SUCCESS(Status))
94 {
95 BaseSetLastNTError(Status);
96 return FALSE;
97 }
98
99 return TRUE;
100 }
101
102
103 /*
104 * @implemented
105 */
106 BOOL WINAPI InitializeCriticalSectionEx(OUT LPCRITICAL_SECTION lpCriticalSection,
107 IN DWORD dwSpinCount,
108 IN DWORD flags)
109 {
110 NTSTATUS Status;
111
112 /* FIXME: Flags ignored */
113
114 /* Initialize the critical section */
115 Status = RtlInitializeCriticalSectionAndSpinCount(
116 (PRTL_CRITICAL_SECTION)lpCriticalSection,
117 dwSpinCount);
118 if (!NT_SUCCESS(Status))
119 {
120 /* Set failure code */
121 BaseSetLastNTError(Status);
122 return FALSE;
123 }
124
125 /* Success */
126 return TRUE;
127 }
128
129
130 /*
131 * @implemented
132 */
133 BOOL
134 WINAPI
135 QueryFullProcessImageNameW(HANDLE hProcess,
136 DWORD dwFlags,
137 LPWSTR lpExeName,
138 PDWORD pdwSize)
139 {
140 BYTE Buffer[sizeof(UNICODE_STRING) + MAX_PATH * sizeof(WCHAR)];
141 UNICODE_STRING *DynamicBuffer = NULL;
142 UNICODE_STRING *Result = NULL;
143 NTSTATUS Status;
144 DWORD Needed;
145
146 Status = NtQueryInformationProcess(hProcess,
147 ProcessImageFileName,
148 Buffer,
149 sizeof(Buffer) - sizeof(WCHAR),
150 &Needed);
151 if (Status == STATUS_INFO_LENGTH_MISMATCH)
152 {
153 DynamicBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Needed + sizeof(WCHAR));
154 if (!DynamicBuffer)
155 {
156 BaseSetLastNTError(STATUS_NO_MEMORY);
157 return FALSE;
158 }
159
160 Status = NtQueryInformationProcess(hProcess,
161 ProcessImageFileName,
162 (LPBYTE)DynamicBuffer,
163 Needed,
164 &Needed);
165 Result = DynamicBuffer;
166 }
167 else Result = (PUNICODE_STRING)Buffer;
168
169 if (!NT_SUCCESS(Status)) goto Cleanup;
170
171 if (Result->Length / sizeof(WCHAR) + 1 > *pdwSize)
172 {
173 Status = STATUS_BUFFER_TOO_SMALL;
174 goto Cleanup;
175 }
176
177 *pdwSize = Result->Length / sizeof(WCHAR);
178 memcpy(lpExeName, Result->Buffer, Result->Length);
179 lpExeName[*pdwSize] = 0;
180
181 Cleanup:
182 RtlFreeHeap(RtlGetProcessHeap(), 0, DynamicBuffer);
183
184 if (!NT_SUCCESS(Status))
185 {
186 BaseSetLastNTError(Status);
187 }
188
189 return !Status;
190 }
191
192
193 /*
194 * @implemented
195 */
196 BOOL
197 WINAPI
198 QueryFullProcessImageNameA(HANDLE hProcess,
199 DWORD dwFlags,
200 LPSTR lpExeName,
201 PDWORD pdwSize)
202 {
203 DWORD pdwSizeW = *pdwSize;
204 BOOL Result;
205 LPWSTR lpExeNameW;
206
207 lpExeNameW = RtlAllocateHeap(RtlGetProcessHeap(),
208 HEAP_ZERO_MEMORY,
209 *pdwSize * sizeof(WCHAR));
210 if (!lpExeNameW)
211 {
212 BaseSetLastNTError(STATUS_NO_MEMORY);
213 return FALSE;
214 }
215
216 Result = QueryFullProcessImageNameW(hProcess, dwFlags, lpExeNameW, &pdwSizeW);
217
218 if (Result)
219 Result = (0 != WideCharToMultiByte(CP_ACP, 0,
220 lpExeNameW,
221 -1,
222 lpExeName,
223 *pdwSize,
224 NULL, NULL));
225
226 if (Result)
227 *pdwSize = strlen(lpExeName);
228
229 RtlFreeHeap(RtlGetProcessHeap(), 0, lpExeNameW);
230 return Result;
231 }
232
233
234 /*
235 * @unimplemented
236 */
237 HRESULT
238 WINAPI
239 GetApplicationRecoveryCallback(IN HANDLE hProcess,
240 OUT APPLICATION_RECOVERY_CALLBACK* pRecoveryCallback,
241 OUT PVOID* ppvParameter,
242 PDWORD dwPingInterval,
243 PDWORD dwFlags)
244 {
245 UNIMPLEMENTED;
246 return E_FAIL;
247 }
248
249
250 /*
251 * @unimplemented
252 */
253 HRESULT
254 WINAPI
255 GetApplicationRestart(IN HANDLE hProcess,
256 OUT PWSTR pwzCommandline OPTIONAL,
257 IN OUT PDWORD pcchSize,
258 OUT PDWORD pdwFlags OPTIONAL)
259 {
260 UNIMPLEMENTED;
261 return E_FAIL;
262 }
263
264
265 /*
266 * @unimplemented
267 */
268 VOID
269 WINAPI
270 RecoveryFinished(IN BOOL bSuccess)
271 {
272 UNIMPLEMENTED;
273 }
274
275
276 /*
277 * @unimplemented
278 */
279 HRESULT
280 WINAPI
281 RecoveryInProgress(OUT PBOOL pbCancelled)
282 {
283 UNIMPLEMENTED;
284 return E_FAIL;
285 }
286
287
288 /*
289 * @unimplemented
290 */
291 HRESULT
292 WINAPI
293 RegisterApplicationRecoveryCallback(IN APPLICATION_RECOVERY_CALLBACK pRecoveryCallback,
294 IN PVOID pvParameter OPTIONAL,
295 DWORD dwPingInterval,
296 DWORD dwFlags)
297 {
298 UNIMPLEMENTED;
299 return E_FAIL;
300 }
301
302
303 /*
304 * @unimplemented
305 */
306 HRESULT
307 WINAPI
308 RegisterApplicationRestart(IN PCWSTR pwzCommandline OPTIONAL,
309 IN DWORD dwFlags)
310 {
311 UNIMPLEMENTED;
312 return E_FAIL;
313 }
314
315
316 /*
317 * @implemented
318 */
319 BOOLEAN
320 WINAPI
321 CreateSymbolicLinkW(IN LPCWSTR lpSymlinkFileName,
322 IN LPCWSTR lpTargetFileName,
323 IN DWORD dwFlags)
324 {
325 IO_STATUS_BLOCK IoStatusBlock;
326 OBJECT_ATTRIBUTES ObjectAttributes;
327 HANDLE hSymlink = NULL;
328 UNICODE_STRING SymlinkFileName = { 0, 0, NULL };
329 UNICODE_STRING TargetFileName = { 0, 0, NULL };
330 BOOLEAN bAllocatedTarget = FALSE, bRelativePath = FALSE;
331 LPWSTR lpTargetFullFileName = NULL;
332 SIZE_T cbPrintName;
333 SIZE_T cbReparseData;
334 PREPARSE_DATA_BUFFER pReparseData = NULL;
335 PBYTE pBufTail;
336 NTSTATUS Status;
337 ULONG dwCreateOptions;
338 DWORD dwErr;
339
340 if(!lpSymlinkFileName || !lpTargetFileName || (dwFlags | SYMBOLIC_LINK_FLAG_DIRECTORY) != SYMBOLIC_LINK_FLAG_DIRECTORY)
341 {
342 SetLastError(ERROR_INVALID_PARAMETER);
343 return FALSE;
344 }
345
346 if(dwFlags & SYMBOLIC_LINK_FLAG_DIRECTORY)
347 dwCreateOptions = FILE_DIRECTORY_FILE;
348 else
349 dwCreateOptions = FILE_NON_DIRECTORY_FILE;
350
351 switch(RtlDetermineDosPathNameType_U(lpTargetFileName))
352 {
353 case RtlPathTypeUnknown:
354 case RtlPathTypeRooted:
355 case RtlPathTypeRelative:
356 bRelativePath = TRUE;
357 RtlInitUnicodeString(&TargetFileName, lpTargetFileName);
358 break;
359
360 case RtlPathTypeDriveRelative:
361 {
362 LPWSTR FilePart;
363 SIZE_T cchTargetFullFileName;
364
365 cchTargetFullFileName = GetFullPathNameW(lpTargetFileName, 0, NULL, &FilePart);
366
367 if(cchTargetFullFileName == 0)
368 {
369 dwErr = GetLastError();
370 goto Cleanup;
371 }
372
373 lpTargetFullFileName = RtlAllocateHeap(RtlGetProcessHeap(), 0, cchTargetFullFileName * sizeof(WCHAR));
374
375 if(lpTargetFullFileName == NULL)
376 {
377 dwErr = ERROR_NOT_ENOUGH_MEMORY;
378 goto Cleanup;
379 }
380
381 if(GetFullPathNameW(lpTargetFileName, cchTargetFullFileName, lpTargetFullFileName, &FilePart) == 0)
382 {
383 dwErr = GetLastError();
384 goto Cleanup;
385 }
386 }
387
388 lpTargetFileName = lpTargetFullFileName;
389
390 // fallthrough
391
392 case RtlPathTypeUncAbsolute:
393 case RtlPathTypeDriveAbsolute:
394 case RtlPathTypeLocalDevice:
395 case RtlPathTypeRootLocalDevice:
396 default:
397 if(!RtlDosPathNameToNtPathName_U(lpTargetFileName, &TargetFileName, NULL, NULL))
398 {
399 bAllocatedTarget = TRUE;
400 dwErr = ERROR_INVALID_PARAMETER;
401 goto Cleanup;
402 }
403 }
404
405 cbPrintName = wcslen(lpTargetFileName) * sizeof(WCHAR);
406 cbReparseData = FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + TargetFileName.Length + cbPrintName;
407 pReparseData = RtlAllocateHeap(RtlGetProcessHeap(), 0, cbReparseData);
408
409 if(pReparseData == NULL)
410 {
411 dwErr = ERROR_NOT_ENOUGH_MEMORY;
412 goto Cleanup;
413 }
414
415 pBufTail = (PBYTE)(pReparseData->SymbolicLinkReparseBuffer.PathBuffer);
416
417 pReparseData->ReparseTag = (ULONG)IO_REPARSE_TAG_SYMLINK;
418 pReparseData->ReparseDataLength = (USHORT)cbReparseData - REPARSE_DATA_BUFFER_HEADER_SIZE;
419 pReparseData->Reserved = 0;
420
421 pReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
422 pReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength = TargetFileName.Length;
423 pBufTail += pReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset;
424 RtlCopyMemory(pBufTail, TargetFileName.Buffer, TargetFileName.Length);
425
426 pReparseData->SymbolicLinkReparseBuffer.PrintNameOffset = pReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
427 pReparseData->SymbolicLinkReparseBuffer.PrintNameLength = (USHORT)cbPrintName;
428 pBufTail += pReparseData->SymbolicLinkReparseBuffer.PrintNameOffset;
429 RtlCopyMemory(pBufTail, lpTargetFileName, cbPrintName);
430
431 pReparseData->SymbolicLinkReparseBuffer.Flags = 0;
432
433 if(bRelativePath)
434 pReparseData->SymbolicLinkReparseBuffer.Flags |= 1; // TODO! give this lone flag a name
435
436 if(!RtlDosPathNameToNtPathName_U(lpSymlinkFileName, &SymlinkFileName, NULL, NULL))
437 {
438 dwErr = ERROR_PATH_NOT_FOUND;
439 goto Cleanup;
440 }
441
442 InitializeObjectAttributes(&ObjectAttributes, &SymlinkFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
443
444 Status = NtCreateFile
445 (
446 &hSymlink,
447 FILE_WRITE_ATTRIBUTES | DELETE | SYNCHRONIZE,
448 &ObjectAttributes,
449 &IoStatusBlock,
450 NULL,
451 FILE_ATTRIBUTE_NORMAL,
452 0,
453 FILE_CREATE,
454 FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT | dwCreateOptions,
455 NULL,
456 0
457 );
458
459 if(!NT_SUCCESS(Status))
460 {
461 dwErr = RtlNtStatusToDosError(Status);
462 goto Cleanup;
463 }
464
465 Status = NtFsControlFile
466 (
467 hSymlink,
468 NULL,
469 NULL,
470 NULL,
471 &IoStatusBlock,
472 FSCTL_SET_REPARSE_POINT,
473 pReparseData,
474 cbReparseData,
475 NULL,
476 0
477 );
478
479 if(!NT_SUCCESS(Status))
480 {
481 FILE_DISPOSITION_INFORMATION DispInfo;
482 DispInfo.DeleteFile = TRUE;
483 NtSetInformationFile(hSymlink, &IoStatusBlock, &DispInfo, sizeof(DispInfo), FileDispositionInformation);
484
485 dwErr = RtlNtStatusToDosError(Status);
486 goto Cleanup;
487 }
488
489 dwErr = NO_ERROR;
490
491 Cleanup:
492 if(hSymlink)
493 NtClose(hSymlink);
494
495 RtlFreeUnicodeString(&SymlinkFileName);
496 if (bAllocatedTarget)
497 {
498 RtlFreeHeap(RtlGetProcessHeap(),
499 0,
500 TargetFileName.Buffer);
501 }
502
503 if(lpTargetFullFileName)
504 RtlFreeHeap(RtlGetProcessHeap(), 0, lpTargetFullFileName);
505
506 if(pReparseData)
507 RtlFreeHeap(RtlGetProcessHeap(), 0, pReparseData);
508
509 if(dwErr)
510 {
511 SetLastError(dwErr);
512 return FALSE;
513 }
514
515 return TRUE;
516 }
517
518
519 /*
520 * @implemented
521 */
522 BOOLEAN
523 NTAPI
524 CreateSymbolicLinkA(IN LPCSTR lpSymlinkFileName,
525 IN LPCSTR lpTargetFileName,
526 IN DWORD dwFlags)
527 {
528 PWCHAR SymlinkW, TargetW;
529 BOOLEAN Ret;
530
531 if(!lpSymlinkFileName || !lpTargetFileName)
532 {
533 SetLastError(ERROR_INVALID_PARAMETER);
534 return FALSE;
535 }
536
537 if (!(SymlinkW = FilenameA2W(lpSymlinkFileName, FALSE)))
538 return FALSE;
539
540 if (!(TargetW = FilenameA2W(lpTargetFileName, TRUE)))
541 return FALSE;
542
543 Ret = CreateSymbolicLinkW(SymlinkW,
544 TargetW,
545 dwFlags);
546
547 RtlFreeHeap(RtlGetProcessHeap(), 0, SymlinkW);
548 RtlFreeHeap(RtlGetProcessHeap(), 0, TargetW);
549
550 return Ret;
551 }
552
553
554 /*
555 * @unimplemented
556 */
557 DWORD
558 WINAPI
559 GetFinalPathNameByHandleW(IN HANDLE hFile,
560 OUT LPWSTR lpszFilePath,
561 IN DWORD cchFilePath,
562 IN DWORD dwFlags)
563 {
564 if (dwFlags & ~(VOLUME_NAME_DOS | VOLUME_NAME_GUID | VOLUME_NAME_NT |
565 VOLUME_NAME_NONE | FILE_NAME_NORMALIZED | FILE_NAME_OPENED))
566 {
567 SetLastError(ERROR_INVALID_PARAMETER);
568 return 0;
569 }
570
571 UNIMPLEMENTED;
572 return 0;
573 }
574
575
576 /*
577 * @implemented
578 */
579 DWORD
580 WINAPI
581 GetFinalPathNameByHandleA(IN HANDLE hFile,
582 OUT LPSTR lpszFilePath,
583 IN DWORD cchFilePath,
584 IN DWORD dwFlags)
585 {
586 WCHAR FilePathW[MAX_PATH];
587 UNICODE_STRING FilePathU;
588 DWORD PrevLastError;
589 DWORD Ret = 0;
590
591 if (cchFilePath != 0 &&
592 cchFilePath > sizeof(FilePathW) / sizeof(FilePathW[0]))
593 {
594 FilePathU.Length = 0;
595 FilePathU.MaximumLength = (USHORT)cchFilePath * sizeof(WCHAR);
596 FilePathU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
597 0,
598 FilePathU.MaximumLength);
599 if (FilePathU.Buffer == NULL)
600 {
601 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
602 return 0;
603 }
604 }
605 else
606 {
607 FilePathU.Length = 0;
608 FilePathU.MaximumLength = sizeof(FilePathW);
609 FilePathU.Buffer = FilePathW;
610 }
611
612 /* save the last error code */
613 PrevLastError = GetLastError();
614 SetLastError(ERROR_SUCCESS);
615
616 /* call the unicode version that does all the work */
617 Ret = GetFinalPathNameByHandleW(hFile,
618 FilePathU.Buffer,
619 cchFilePath,
620 dwFlags);
621
622 if (GetLastError() == ERROR_SUCCESS)
623 {
624 /* no error, restore the last error code and convert the string */
625 SetLastError(PrevLastError);
626
627 Ret = FilenameU2A_FitOrFail(lpszFilePath,
628 cchFilePath,
629 &FilePathU);
630 }
631
632 /* free allocated memory if necessary */
633 if (FilePathU.Buffer != FilePathW)
634 {
635 RtlFreeHeap(RtlGetProcessHeap(),
636 0,
637 FilePathU.Buffer);
638 }
639
640 return Ret;
641 }
642
643
644 /*
645 * @unimplemented
646 */
647 BOOL
648 WINAPI
649 SetFileBandwidthReservation(IN HANDLE hFile,
650 IN DWORD nPeriodMilliseconds,
651 IN DWORD nBytesPerPeriod,
652 IN BOOL bDiscardable,
653 OUT LPDWORD lpTransferSize,
654 OUT LPDWORD lpNumOutstandingRequests)
655 {
656 UNIMPLEMENTED;
657 return FALSE;
658 }
659
660
661 /*
662 * @unimplemented
663 */
664 BOOL
665 WINAPI
666 GetFileBandwidthReservation(IN HANDLE hFile,
667 OUT LPDWORD lpPeriodMilliseconds,
668 OUT LPDWORD lpBytesPerPeriod,
669 OUT LPBOOL pDiscardable,
670 OUT LPDWORD lpTransferSize,
671 OUT LPDWORD lpNumOutstandingRequests)
672 {
673 UNIMPLEMENTED;
674 return FALSE;
675 }
676
677
678 /*
679 * @unimplemented
680 */
681 HANDLE
682 WINAPI
683 OpenFileById(IN HANDLE hFile,
684 IN LPFILE_ID_DESCRIPTOR lpFileID,
685 IN DWORD dwDesiredAccess,
686 IN DWORD dwShareMode,
687 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL,
688 IN DWORD dwFlags)
689 {
690 UNIMPLEMENTED;
691 return INVALID_HANDLE_VALUE;
692 }
693
694
695 /*
696 * @implemented
697 */
698 ULONGLONG
699 WINAPI
700 GetTickCount64(VOID)
701 {
702 ULARGE_INTEGER TickCount;
703
704 while (TRUE)
705 {
706 TickCount.HighPart = (ULONG)SharedUserData->TickCount.High1Time;
707 TickCount.LowPart = SharedUserData->TickCount.LowPart;
708
709 if (TickCount.HighPart == (ULONG)SharedUserData->TickCount.High2Time) break;
710
711 YieldProcessor();
712 }
713
714 return (UInt32x32To64(TickCount.LowPart, SharedUserData->TickCountMultiplier) >> 24) +
715 (UInt32x32To64(TickCount.HighPart, SharedUserData->TickCountMultiplier) << 8);
716 }
717
718 #endif
719
720 /*
721 Vista+ MUI support functions
722
723 References:
724 Evolution of MUI Support across Windows Versions: http://msdn.microsoft.com/en-US/library/ee264317.aspx
725 Comparing Windows XP Professional Multilingual Options: http://technet.microsoft.com/en-us/library/bb457045.aspx
726
727 More info:
728 http://msdn.microsoft.com/en-us/goglobal/bb978454.aspx
729 http://msdn.microsoft.com/en-us/library/dd319074.aspx
730 */
731
732 /* FUNCTIONS *****************************************************************/
733
734 BOOL
735 WINAPI
736 GetFileMUIInfo(
737 DWORD dwFlags,
738 PCWSTR pcwszFilePath,
739 PFILEMUIINFO pFileMUIInfo,
740 DWORD *pcbFileMUIInfo)
741 {
742 DPRINT1("%x %p %p %p\n", dwFlags, pcwszFilePath, pFileMUIInfo, pcbFileMUIInfo);
743 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
744 return FALSE;
745 }
746
747 /*
748 * @unimplemented
749 */
750 BOOL
751 WINAPI
752 GetFileMUIPath(
753 DWORD dwFlags,
754 PCWSTR pcwszFilePath,
755 PWSTR pwszLanguage,
756 PULONG pcchLanguage,
757 PWSTR pwszFileMUIPath,
758 PULONG pcchFileMUIPath,
759 PULONGLONG pululEnumerator)
760 {
761 DPRINT1("%x %p %p %p %p %p\n", dwFlags, pcwszFilePath, pwszLanguage, pwszFileMUIPath, pcchFileMUIPath, pululEnumerator);
762 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
763 return FALSE;
764 }
765
766 /*
767 * @unimplemented
768 */
769 BOOL
770 WINAPI
771 GetProcessPreferredUILanguages(
772 DWORD dwFlags,
773 PULONG pulNumLanguages,
774 PZZWSTR pwszLanguagesBuffer,
775 PULONG pcchLanguagesBuffer)
776 {
777 DPRINT1("%x %p %p %p\n", dwFlags, pulNumLanguages, pwszLanguagesBuffer, pcchLanguagesBuffer);
778 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
779 return FALSE;
780 }
781
782 /*
783 * @unimplemented
784 */
785 BOOL
786 WINAPI
787 GetSystemPreferredUILanguages(
788 DWORD dwFlags,
789 PULONG pulNumLanguages,
790 PZZWSTR pwszLanguagesBuffer,
791 PULONG pcchLanguagesBuffer)
792 {
793 DPRINT1("%x %p %p %p\n", dwFlags, pulNumLanguages, pwszLanguagesBuffer, pcchLanguagesBuffer);
794 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
795 return FALSE;
796 }
797
798 /*
799 * @unimplemented
800 */
801 BOOL
802 WINAPI
803 GetThreadPreferredUILanguages(
804 DWORD dwFlags,
805 PULONG pulNumLanguages,
806 PZZWSTR pwszLanguagesBuffer,
807 PULONG pcchLanguagesBuffer)
808 {
809 DPRINT1("%x %p %p %p\n", dwFlags, pulNumLanguages, pwszLanguagesBuffer, pcchLanguagesBuffer);
810 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
811 return FALSE;
812 }
813
814 /*
815 * @unimplemented
816 */
817 LANGID
818 WINAPI
819 GetThreadUILanguage(VOID)
820 {
821 UNIMPLEMENTED;
822 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
823 return 0;
824 }
825
826 /*
827 * @unimplemented
828 */
829 BOOL
830 WINAPI
831 GetUILanguageInfo(
832 DWORD dwFlags,
833 PCZZWSTR pwmszLanguage,
834 PZZWSTR pwszFallbackLanguages,
835 PDWORD pcchFallbackLanguages,
836 PDWORD pdwAttributes)
837 {
838 DPRINT1("%x %p %p %p %p\n", dwFlags, pwmszLanguage, pwszFallbackLanguages, pcchFallbackLanguages, pdwAttributes);
839 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
840 return FALSE;
841 }
842
843
844 /*
845 * @unimplemented
846 */
847 BOOL
848 WINAPI
849 GetUserPreferredUILanguages(
850 DWORD dwFlags,
851 PULONG pulNumLanguages,
852 PZZWSTR pwszLanguagesBuffer,
853 PULONG pcchLanguagesBuffer)
854 {
855 DPRINT1("%x %p %p %p\n", dwFlags, pulNumLanguages, pwszLanguagesBuffer, pcchLanguagesBuffer);
856 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
857 return FALSE;
858 }
859
860 /*
861 * @unimplemented
862 */
863 BOOL
864 WINAPI
865 SetProcessPreferredUILanguages(
866 DWORD dwFlags,
867 PCZZWSTR pwszLanguagesBuffer,
868 PULONG pulNumLanguages)
869 {
870 DPRINT1("%x %p %p\n", dwFlags, pwszLanguagesBuffer, pulNumLanguages);
871 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
872 return FALSE;
873 }
874
875
876 /*
877 * @unimplemented
878 */
879 BOOL
880 WINAPI
881 SetThreadPreferredUILanguages(
882 DWORD dwFlags,
883 PCZZWSTR pwszLanguagesBuffer,
884 PULONG pulNumLanguages
885 )
886 {
887 DPRINT1("%x %p %p\n", dwFlags, pwszLanguagesBuffer, pulNumLanguages);
888 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
889 return FALSE;
890 }
891