kernel32: Implement CreateHardLink.
authorAndrey Turkin <andrey.turkin@gmail.com>
Sun, 16 May 2010 22:28:56 +0000 (02:28 +0400)
committerAlexandre Julliard <julliard@winehq.org>
Mon, 17 May 2010 12:43:26 +0000 (14:43 +0200)
dlls/kernel32/path.c

index 2b69e8cd7f451b4331c2aa99c03f12226f4f2b6f..c319cb593b4687e1c97d9910b9c4f2deee59b87e 100644 (file)
@@ -1217,10 +1217,54 @@ BOOL WINAPI MoveFileA( LPCSTR source, LPCSTR dest )
 BOOL WINAPI CreateHardLinkW(LPCWSTR lpFileName, LPCWSTR lpExistingFileName,
     LPSECURITY_ATTRIBUTES lpSecurityAttributes)
 {
-    FIXME("(%s, %s, %p): stub\n", debugstr_w(lpFileName),
+    NTSTATUS status;
+    UNICODE_STRING ntDest, ntSource;
+    ANSI_STRING unixDest, unixSource;
+    BOOL ret = FALSE;
+
+    TRACE("(%s, %s, %p)\n", debugstr_w(lpFileName),
         debugstr_w(lpExistingFileName), lpSecurityAttributes);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+
+    ntDest.Buffer = ntSource.Buffer = NULL;
+    if (!RtlDosPathNameToNtPathName_U( lpFileName, &ntDest, NULL, NULL ) ||
+        !RtlDosPathNameToNtPathName_U( lpExistingFileName, &ntSource, NULL, NULL ))
+    {
+        SetLastError( ERROR_PATH_NOT_FOUND );
+        goto err;
+    }
+
+    unixSource.Buffer = unixDest.Buffer = NULL;
+    status = wine_nt_to_unix_file_name( &ntSource, &unixSource, FILE_OPEN, FALSE );
+    if (!status)
+    {
+        status = wine_nt_to_unix_file_name( &ntDest, &unixDest, FILE_CREATE, FALSE );
+        if (!status) /* destination must not exist */
+        {
+            status = STATUS_OBJECT_NAME_EXISTS;
+        } else if (status == STATUS_NO_SUCH_FILE)
+        {
+            status = STATUS_SUCCESS;
+        }
+    }
+
+    if (status)
+         SetLastError( RtlNtStatusToDosError(status) );
+    else if (!link( unixSource.Buffer, unixDest.Buffer ))
+    {
+        TRACE("Hardlinked '%s' to '%s'\n", debugstr_a( unixDest.Buffer ),
+                debugstr_a( unixSource.Buffer ));
+        ret = TRUE;
+    }
+    else
+        FILE_SetDosError();
+
+    RtlFreeAnsiString( &unixSource );
+    RtlFreeAnsiString( &unixDest );
+
+err:
+    RtlFreeUnicodeString( &ntSource );
+    RtlFreeUnicodeString( &ntDest );
+    return ret;
 }
 
 
@@ -1230,10 +1274,25 @@ BOOL WINAPI CreateHardLinkW(LPCWSTR lpFileName, LPCWSTR lpExistingFileName,
 BOOL WINAPI CreateHardLinkA(LPCSTR lpFileName, LPCSTR lpExistingFileName,
     LPSECURITY_ATTRIBUTES lpSecurityAttributes)
 {
-    FIXME("(%s, %s, %p): stub\n", debugstr_a(lpFileName),
-        debugstr_a(lpExistingFileName), lpSecurityAttributes);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    WCHAR *sourceW, *destW;
+    BOOL res;
+
+    if (!(sourceW = FILE_name_AtoW( lpExistingFileName, TRUE )))
+    {
+        return FALSE;
+    }
+    if (!(destW = FILE_name_AtoW( lpFileName, TRUE )))
+    {
+        HeapFree( GetProcessHeap(), 0, sourceW );
+        return FALSE;
+    }
+
+    res = CreateHardLinkW( destW, sourceW, lpSecurityAttributes );
+
+    HeapFree( GetProcessHeap(), 0, sourceW );
+    HeapFree( GetProcessHeap(), 0, destW );
+
+    return res;
 }