[WLAN-BRINGUP]
[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 ULONG CsrRequest = MAKE_CSR_API(GET_HISTORY_INFO, CSR_CONSOLE);
323 NTSTATUS Status;
324 if (lpConsoleHistoryInfo->cbSize != sizeof(CONSOLE_HISTORY_INFO))
325 {
326 SetLastError(ERROR_INVALID_PARAMETER);
327 return FALSE;
328 }
329 Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE));
330 if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
331 {
332 BaseSetLastNTError(Status);
333 return FALSE;
334 }
335 lpConsoleHistoryInfo->HistoryBufferSize = Request.Data.GetHistoryInfo.HistoryBufferSize;
336 lpConsoleHistoryInfo->NumberOfHistoryBuffers = Request.Data.GetHistoryInfo.NumberOfHistoryBuffers;
337 lpConsoleHistoryInfo->dwFlags = Request.Data.GetHistoryInfo.dwFlags;
338 return TRUE;
339 }
340
341
342 /*--------------------------------------------------------------
343 * SetConsoleHistoryInfo
344 *
345 * @implemented
346 */
347 BOOL
348 WINAPI
349 SetConsoleHistoryInfo(IN PCONSOLE_HISTORY_INFO lpConsoleHistoryInfo)
350 {
351 CSR_API_MESSAGE Request;
352 ULONG CsrRequest = MAKE_CSR_API(GET_HISTORY_INFO, CSR_CONSOLE);
353 NTSTATUS Status;
354 if (lpConsoleHistoryInfo->cbSize != sizeof(CONSOLE_HISTORY_INFO))
355 {
356 SetLastError(ERROR_INVALID_PARAMETER);
357 return FALSE;
358 }
359 Request.Data.SetHistoryInfo.HistoryBufferSize = lpConsoleHistoryInfo->HistoryBufferSize;
360 Request.Data.SetHistoryInfo.NumberOfHistoryBuffers = lpConsoleHistoryInfo->NumberOfHistoryBuffers;
361 Request.Data.SetHistoryInfo.dwFlags = lpConsoleHistoryInfo->dwFlags;
362 Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE));
363 if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
364 {
365 BaseSetLastNTError(Status);
366 return FALSE;
367 }
368 return TRUE;
369 }
370
371
372 /*--------------------------------------------------------------
373 * GetConsoleOriginalTitleW
374 *
375 * @unimplemented
376 */
377 DWORD
378 WINAPI
379 GetConsoleOriginalTitleW(OUT LPWSTR lpConsoleTitle,
380 IN DWORD nSize)
381 {
382 DPRINT1("GetConsoleOriginalTitleW(0x%p, 0x%x) UNIMPLEMENTED!\n", lpConsoleTitle, nSize);
383 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
384 return 0;
385 }
386
387
388 /*--------------------------------------------------------------
389 * GetConsoleOriginalTitleA
390 *
391 * @unimplemented
392 */
393 DWORD
394 WINAPI
395 GetConsoleOriginalTitleA(OUT LPSTR lpConsoleTitle,
396 IN DWORD nSize)
397 {
398 DPRINT1("GetConsoleOriginalTitleA(0x%p, 0x%x) UNIMPLEMENTED!\n", lpConsoleTitle, nSize);
399 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
400 return 0;
401 }
402
403
404 /*--------------------------------------------------------------
405 * GetConsoleScreenBufferInfoEx
406 *
407 * @unimplemented
408 */
409 BOOL
410 WINAPI
411 GetConsoleScreenBufferInfoEx(IN HANDLE hConsoleOutput,
412 OUT PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx)
413 {
414 DPRINT1("GetConsoleScreenBufferInfoEx(0x%p, 0x%p) UNIMPLEMENTED!\n", hConsoleOutput, lpConsoleScreenBufferInfoEx);
415 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
416 return FALSE;
417 }
418
419
420 /*--------------------------------------------------------------
421 * SetConsoleScreenBufferInfoEx
422 *
423 * @unimplemented
424 */
425 BOOL
426 WINAPI
427 SetConsoleScreenBufferInfoEx(IN HANDLE hConsoleOutput,
428 IN PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx)
429 {
430 DPRINT1("SetConsoleScreenBufferInfoEx(0x%p, 0x%p) UNIMPLEMENTED!\n", hConsoleOutput, lpConsoleScreenBufferInfoEx);
431 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
432 return FALSE;
433 }
434
435
436 /*--------------------------------------------------------------
437 * GetCurrentConsoleFontEx
438 *
439 * @unimplemented
440 */
441 BOOL
442 WINAPI
443 GetCurrentConsoleFontEx(IN HANDLE hConsoleOutput,
444 IN BOOL bMaximumWindow,
445 OUT PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx)
446 {
447 DPRINT1("GetCurrentConsoleFontEx(0x%p, 0x%x, 0x%p) UNIMPLEMENTED!\n", hConsoleOutput, bMaximumWindow, lpConsoleCurrentFontEx);
448 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
449 return FALSE;
450 }
451
452
453 /*
454 * @implemented
455 */
456 BOOLEAN
457 WINAPI
458 CreateSymbolicLinkW(IN LPCWSTR lpSymlinkFileName,
459 IN LPCWSTR lpTargetFileName,
460 IN DWORD dwFlags)
461 {
462 IO_STATUS_BLOCK IoStatusBlock;
463 OBJECT_ATTRIBUTES ObjectAttributes;
464 HANDLE hSymlink = NULL;
465 UNICODE_STRING SymlinkFileName = { 0, 0, NULL };
466 UNICODE_STRING TargetFileName = { 0, 0, NULL };
467 BOOLEAN bAllocatedTarget = FALSE, bRelativePath = FALSE;
468 LPWSTR lpTargetFullFileName = NULL;
469 SIZE_T cbPrintName;
470 SIZE_T cbReparseData;
471 PREPARSE_DATA_BUFFER pReparseData = NULL;
472 PBYTE pBufTail;
473 NTSTATUS Status;
474 ULONG dwCreateOptions;
475 DWORD dwErr;
476
477 if(!lpSymlinkFileName || !lpTargetFileName || (dwFlags | SYMBOLIC_LINK_FLAG_DIRECTORY) != SYMBOLIC_LINK_FLAG_DIRECTORY)
478 {
479 SetLastError(ERROR_INVALID_PARAMETER);
480 return FALSE;
481 }
482
483 if(dwFlags & SYMBOLIC_LINK_FLAG_DIRECTORY)
484 dwCreateOptions = FILE_DIRECTORY_FILE;
485 else
486 dwCreateOptions = FILE_NON_DIRECTORY_FILE;
487
488 switch(RtlDetermineDosPathNameType_U(lpTargetFileName))
489 {
490 case RtlPathTypeUnknown:
491 case RtlPathTypeRooted:
492 case RtlPathTypeRelative:
493 bRelativePath = TRUE;
494 RtlInitUnicodeString(&TargetFileName, lpTargetFileName);
495 break;
496
497 case RtlPathTypeDriveRelative:
498 {
499 LPWSTR FilePart;
500 SIZE_T cchTargetFullFileName;
501
502 cchTargetFullFileName = GetFullPathNameW(lpTargetFileName, 0, NULL, &FilePart);
503
504 if(cchTargetFullFileName == 0)
505 {
506 dwErr = GetLastError();
507 goto Cleanup;
508 }
509
510 lpTargetFullFileName = RtlAllocateHeap(RtlGetProcessHeap(), 0, cchTargetFullFileName * sizeof(WCHAR));
511
512 if(lpTargetFullFileName == NULL)
513 {
514 dwErr = ERROR_NOT_ENOUGH_MEMORY;
515 goto Cleanup;
516 }
517
518 if(GetFullPathNameW(lpTargetFileName, cchTargetFullFileName, lpTargetFullFileName, &FilePart) == 0)
519 {
520 dwErr = GetLastError();
521 goto Cleanup;
522 }
523 }
524
525 lpTargetFileName = lpTargetFullFileName;
526
527 // fallthrough
528
529 case RtlPathTypeUncAbsolute:
530 case RtlPathTypeDriveAbsolute:
531 case RtlPathTypeLocalDevice:
532 case RtlPathTypeRootLocalDevice:
533 default:
534 if(!RtlDosPathNameToNtPathName_U(lpTargetFileName, &TargetFileName, NULL, NULL))
535 {
536 bAllocatedTarget = TRUE;
537 dwErr = ERROR_INVALID_PARAMETER;
538 goto Cleanup;
539 }
540 }
541
542 cbPrintName = wcslen(lpTargetFileName) * sizeof(WCHAR);
543 cbReparseData = FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + TargetFileName.Length + cbPrintName;
544 pReparseData = RtlAllocateHeap(RtlGetProcessHeap(), 0, cbReparseData);
545
546 if(pReparseData == NULL)
547 {
548 dwErr = ERROR_NOT_ENOUGH_MEMORY;
549 goto Cleanup;
550 }
551
552 pBufTail = (PBYTE)(pReparseData->SymbolicLinkReparseBuffer.PathBuffer);
553
554 pReparseData->ReparseTag = (ULONG)IO_REPARSE_TAG_SYMLINK;
555 pReparseData->ReparseDataLength = (USHORT)cbReparseData - REPARSE_DATA_BUFFER_HEADER_SIZE;
556 pReparseData->Reserved = 0;
557
558 pReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
559 pReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength = TargetFileName.Length;
560 pBufTail += pReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset;
561 RtlCopyMemory(pBufTail, TargetFileName.Buffer, TargetFileName.Length);
562
563 pReparseData->SymbolicLinkReparseBuffer.PrintNameOffset = pReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
564 pReparseData->SymbolicLinkReparseBuffer.PrintNameLength = (USHORT)cbPrintName;
565 pBufTail += pReparseData->SymbolicLinkReparseBuffer.PrintNameOffset;
566 RtlCopyMemory(pBufTail, lpTargetFileName, cbPrintName);
567
568 pReparseData->SymbolicLinkReparseBuffer.Flags = 0;
569
570 if(bRelativePath)
571 pReparseData->SymbolicLinkReparseBuffer.Flags |= 1; // TODO! give this lone flag a name
572
573 if(!RtlDosPathNameToNtPathName_U(lpSymlinkFileName, &SymlinkFileName, NULL, NULL))
574 {
575 dwErr = ERROR_PATH_NOT_FOUND;
576 goto Cleanup;
577 }
578
579 InitializeObjectAttributes(&ObjectAttributes, &SymlinkFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
580
581 Status = NtCreateFile
582 (
583 &hSymlink,
584 FILE_WRITE_ATTRIBUTES | DELETE | SYNCHRONIZE,
585 &ObjectAttributes,
586 &IoStatusBlock,
587 NULL,
588 FILE_ATTRIBUTE_NORMAL,
589 0,
590 FILE_CREATE,
591 FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT | dwCreateOptions,
592 NULL,
593 0
594 );
595
596 if(!NT_SUCCESS(Status))
597 {
598 dwErr = RtlNtStatusToDosError(Status);
599 goto Cleanup;
600 }
601
602 Status = NtFsControlFile
603 (
604 hSymlink,
605 NULL,
606 NULL,
607 NULL,
608 &IoStatusBlock,
609 FSCTL_SET_REPARSE_POINT,
610 pReparseData,
611 cbReparseData,
612 NULL,
613 0
614 );
615
616 if(!NT_SUCCESS(Status))
617 {
618 FILE_DISPOSITION_INFORMATION DispInfo;
619 DispInfo.DeleteFile = TRUE;
620 NtSetInformationFile(hSymlink, &IoStatusBlock, &DispInfo, sizeof(DispInfo), FileDispositionInformation);
621
622 dwErr = RtlNtStatusToDosError(Status);
623 goto Cleanup;
624 }
625
626 dwErr = NO_ERROR;
627
628 Cleanup:
629 if(hSymlink)
630 NtClose(hSymlink);
631
632 RtlFreeUnicodeString(&SymlinkFileName);
633 if (bAllocatedTarget)
634 {
635 RtlFreeHeap(RtlGetProcessHeap(),
636 0,
637 TargetFileName.Buffer);
638 }
639
640 if(lpTargetFullFileName)
641 RtlFreeHeap(RtlGetProcessHeap(), 0, lpTargetFullFileName);
642
643 if(pReparseData)
644 RtlFreeHeap(RtlGetProcessHeap(), 0, pReparseData);
645
646 if(dwErr)
647 {
648 SetLastError(dwErr);
649 return FALSE;
650 }
651
652 return TRUE;
653 }
654
655
656 /*
657 * @implemented
658 */
659 BOOLEAN
660 NTAPI
661 CreateSymbolicLinkA(IN LPCSTR lpSymlinkFileName,
662 IN LPCSTR lpTargetFileName,
663 IN DWORD dwFlags)
664 {
665 PWCHAR SymlinkW, TargetW;
666 BOOLEAN Ret;
667
668 if(!lpSymlinkFileName || !lpTargetFileName)
669 {
670 SetLastError(ERROR_INVALID_PARAMETER);
671 return FALSE;
672 }
673
674 if (!(SymlinkW = FilenameA2W(lpSymlinkFileName, FALSE)))
675 return FALSE;
676
677 if (!(TargetW = FilenameA2W(lpTargetFileName, TRUE)))
678 return FALSE;
679
680 Ret = CreateSymbolicLinkW(SymlinkW,
681 TargetW,
682 dwFlags);
683
684 RtlFreeHeap(RtlGetProcessHeap(), 0, SymlinkW);
685 RtlFreeHeap(RtlGetProcessHeap(), 0, TargetW);
686
687 return Ret;
688 }
689
690 /*
691 * @unimplemented
692 */
693 DWORD
694 WINAPI
695 GetFinalPathNameByHandleW(IN HANDLE hFile,
696 OUT LPWSTR lpszFilePath,
697 IN DWORD cchFilePath,
698 IN DWORD dwFlags)
699 {
700 if (dwFlags & ~(VOLUME_NAME_DOS | VOLUME_NAME_GUID | VOLUME_NAME_NT |
701 VOLUME_NAME_NONE | FILE_NAME_NORMALIZED | FILE_NAME_OPENED))
702 {
703 SetLastError(ERROR_INVALID_PARAMETER);
704 return 0;
705 }
706
707 UNIMPLEMENTED;
708 return 0;
709 }
710
711 /*
712 * @implemented
713 */
714 DWORD
715 WINAPI
716 GetFinalPathNameByHandleA(IN HANDLE hFile,
717 OUT LPSTR lpszFilePath,
718 IN DWORD cchFilePath,
719 IN DWORD dwFlags)
720 {
721 WCHAR FilePathW[MAX_PATH];
722 UNICODE_STRING FilePathU;
723 DWORD PrevLastError;
724 DWORD Ret = 0;
725
726 if (cchFilePath != 0 &&
727 cchFilePath > sizeof(FilePathW) / sizeof(FilePathW[0]))
728 {
729 FilePathU.Length = 0;
730 FilePathU.MaximumLength = (USHORT)cchFilePath * sizeof(WCHAR);
731 FilePathU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
732 0,
733 FilePathU.MaximumLength);
734 if (FilePathU.Buffer == NULL)
735 {
736 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
737 return 0;
738 }
739 }
740 else
741 {
742 FilePathU.Length = 0;
743 FilePathU.MaximumLength = sizeof(FilePathW);
744 FilePathU.Buffer = FilePathW;
745 }
746
747 /* save the last error code */
748 PrevLastError = GetLastError();
749 SetLastError(ERROR_SUCCESS);
750
751 /* call the unicode version that does all the work */
752 Ret = GetFinalPathNameByHandleW(hFile,
753 FilePathU.Buffer,
754 cchFilePath,
755 dwFlags);
756
757 if (GetLastError() == ERROR_SUCCESS)
758 {
759 /* no error, restore the last error code and convert the string */
760 SetLastError(PrevLastError);
761
762 Ret = FilenameU2A_FitOrFail(lpszFilePath,
763 cchFilePath,
764 &FilePathU);
765 }
766
767 /* free allocated memory if necessary */
768 if (FilePathU.Buffer != FilePathW)
769 {
770 RtlFreeHeap(RtlGetProcessHeap(),
771 0,
772 FilePathU.Buffer);
773 }
774
775 return Ret;
776 }
777
778 /*
779 * @unimplemented
780 */
781 BOOL
782 WINAPI
783 SetFileBandwidthReservation(IN HANDLE hFile,
784 IN DWORD nPeriodMilliseconds,
785 IN DWORD nBytesPerPeriod,
786 IN BOOL bDiscardable,
787 OUT LPDWORD lpTransferSize,
788 OUT LPDWORD lpNumOutstandingRequests)
789 {
790 UNIMPLEMENTED;
791 return FALSE;
792 }
793
794
795 /*
796 * @unimplemented
797 */
798 BOOL
799 WINAPI
800 GetFileBandwidthReservation(IN HANDLE hFile,
801 OUT LPDWORD lpPeriodMilliseconds,
802 OUT LPDWORD lpBytesPerPeriod,
803 OUT LPBOOL pDiscardable,
804 OUT LPDWORD lpTransferSize,
805 OUT LPDWORD lpNumOutstandingRequests)
806 {
807 UNIMPLEMENTED;
808 return FALSE;
809 }
810
811
812 /*
813 * @unimplemented
814 */
815 BOOL
816 WINAPI
817 SetFileCompletionNotificationModes(IN HANDLE FileHandle,
818 IN UCHAR Flags)
819 {
820 if (Flags & ~(FILE_SKIP_COMPLETION_PORT_ON_SUCCESS | FILE_SKIP_SET_EVENT_ON_HANDLE))
821 {
822 SetLastError(ERROR_INVALID_PARAMETER);
823 return FALSE;
824 }
825
826 UNIMPLEMENTED;
827 return FALSE;
828 }
829
830
831 /*
832 * @unimplemented
833 */
834 HANDLE
835 WINAPI
836 OpenFileById(IN HANDLE hFile,
837 IN LPFILE_ID_DESCRIPTOR lpFileID,
838 IN DWORD dwDesiredAccess,
839 IN DWORD dwShareMode,
840 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL,
841 IN DWORD dwFlags)
842 {
843 UNIMPLEMENTED;
844 return INVALID_HANDLE_VALUE;
845 }
846
847 #endif
848
849 /*
850 * @implemented
851 */
852 ULONGLONG
853 WINAPI
854 GetTickCount64(VOID)
855 {
856 ULARGE_INTEGER TickCount;
857
858 while (TRUE)
859 {
860 TickCount.HighPart = (ULONG)SharedUserData->TickCount.High1Time;
861 TickCount.LowPart = SharedUserData->TickCount.LowPart;
862
863 if (TickCount.HighPart == (ULONG)SharedUserData->TickCount.High2Time) break;
864
865 YieldProcessor();
866 }
867
868 return (UInt32x32To64(TickCount.LowPart, SharedUserData->TickCountMultiplier) >> 24) +
869 (UInt32x32To64(TickCount.HighPart, SharedUserData->TickCountMultiplier) << 8);
870 }