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