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