source: trunk/src/kernel32/directory.cpp@ 4265

Last change on this file since 4265 was 3799, checked in by sandervl, 25 years ago

CopyFileExA/W, CreateDirectoryExA/W unstubbed, GetShortPathNameA/W fixes

File size: 20.7 KB
Line 
1/* $Id: directory.cpp,v 1.29 2000-07-04 08:41:13 sandervl Exp $ */
2
3/*
4 * Win32 Directory functions for OS/2
5 *
6 * Copyright 1998 Sander van Leeuwen
7 *
8 * NOTE: Directory creation has to be done in install program (odin\win)
9 *
10 * Parts based on Wine code (991031) (files\directory.c)
11 *
12 * DOS directories functions
13 *
14 * Copyright 1995 Alexandre Julliard
15 *
16 * TODO:
17 * - System/window directories should be created by install program!
18 *
19 * Project Odin Software License can be found in LICENSE.TXT
20 *
21 */
22
23
24/*****************************************************************************
25 * Includes *
26 *****************************************************************************/
27
28#include <odin.h>
29#include <odinwrap.h>
30#include <os2win.h>
31#include <stdlib.h>
32#include <unicode.h>
33#include <heapstring.h>
34#include <options.h>
35#include "initterm.h"
36#include <win\file.h>
37#include <string.h>
38#include "oslibdos.h"
39#include "profile.h"
40
41#define DBG_LOCALLOG DBG_directory
42#include "dbglocal.h"
43
44ODINDEBUGCHANNEL(KERNEL32-DIRECTORY)
45
46
47/*****************************************************************************
48 * Local Prototypes *
49 *****************************************************************************/
50
51
52static char DIR_Windows[MAX_PATHNAME_LEN];
53static char DIR_System[MAX_PATHNAME_LEN];
54
55//******************************************************************************
56//******************************************************************************
57char *InternalGetWindowsDirectoryA()
58{
59 return DIR_Windows;
60}
61//******************************************************************************
62//******************************************************************************
63char *InternalGetSystemDirectoryA()
64{
65 return DIR_System;
66}
67//******************************************************************************
68//******************************************************************************
69void InitDirectories()
70{
71 char *endofwinpath, *tmp;
72 int len;
73
74 strcpy(DIR_System, kernel32Path);
75 len = strlen(DIR_System);
76 if(DIR_System[len-1] == '\\') {
77 DIR_System[len-1] = 0;
78 }
79 len = ODIN_PROFILE_GetOdinIniString(ODINDIRECTORIES,"WINDOWS","",DIR_Windows,sizeof(DIR_Windows));
80 if (len > 2) {
81 if(DIR_Windows[len-1] == '\\') {
82 DIR_Windows[len-1] = 0;
83 }
84 }
85 else {
86 strcpy(DIR_Windows, DIR_System);
87 endofwinpath = tmp = strchr(DIR_Windows, '\\');
88 while(tmp) {
89 tmp = strchr(endofwinpath+1, '\\');
90 if(tmp)
91 endofwinpath = tmp;
92 }
93 if(endofwinpath) {
94 *endofwinpath = 0; //remove \SYSTEM32
95 }
96 else DebugInt3();
97 }
98}
99/*****************************************************************************
100 * Name : GetCurrentDirectoryA
101 * Purpose : query the current directory
102 * Parameters:
103 * Variables :
104 * Result :
105 * Remark :
106 * Status :
107 *
108 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
109 *****************************************************************************/
110
111ODINFUNCTION2(UINT, GetCurrentDirectoryA, UINT, nBufferLength,
112 LPSTR, lpBuffer)
113{
114 return O32_GetCurrentDirectory(nBufferLength, lpBuffer);
115}
116
117
118/*****************************************************************************
119 * Name : GetCurrentDirectoryW
120 * Purpose : query the current directory
121 * Parameters:
122 * Variables :
123 * Result :
124 * Remark :
125 * Status :
126 *
127 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
128 *****************************************************************************/
129
130ODINFUNCTION2(UINT, GetCurrentDirectoryW, UINT, nBufferLength,
131 LPWSTR, lpBuffer)
132{
133 char *asciidir = (char *)malloc(nBufferLength+1);
134 int rc;
135
136 rc = O32_GetCurrentDirectory(nBufferLength, asciidir);
137 if(rc != 0)
138 AsciiToUnicode(asciidir, lpBuffer);
139 free(asciidir);
140 return(rc);
141}
142
143
144/*****************************************************************************
145 * Name : SetCurrentDirectoryA
146 * Purpose :
147 * Parameters:
148 * Variables :
149 * Result :
150 * Remark :
151 * Status :
152 *
153 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
154 *****************************************************************************/
155
156
157ODINFUNCTION1(BOOL, SetCurrentDirectoryA,
158 LPCSTR, lpstrDirectory)
159{
160 if(HIWORD(lpstrDirectory) == 0)
161 {
162 SetLastError(ERROR_INVALID_PARAMETER);
163 return FALSE;
164 }
165
166 // cut off trailing backslashes
167 // not if a process wants to change to the root directory
168 int len = lstrlenA(lpstrDirectory);
169 if ( ( (lpstrDirectory[len - 1] == '\\') ||
170 (lpstrDirectory[len - 1] == '/') ) &&
171 (len != 1) )
172 {
173 LPSTR lpTemp = (LPSTR)_alloca(len);
174 lstrcpynA(lpTemp,
175 lpstrDirectory,
176 len); // len is including trailing NULL!!
177 lpstrDirectory = lpTemp;
178 }
179
180 dprintf(("SetCurrentDirectoryA %s", lpstrDirectory));
181 return O32_SetCurrentDirectory((LPSTR)lpstrDirectory);
182}
183
184
185/*****************************************************************************
186 * Name : SetCurrentDirectoryW
187 * Purpose :
188 * Parameters:
189 * Variables :
190 * Result :
191 * Remark :
192 * Status :
193 *
194 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
195 *****************************************************************************/
196
197ODINFUNCTION1(BOOL,SetCurrentDirectoryW,LPCWSTR,lpPathName)
198{
199 char *asciipath;
200 BOOL rc;
201
202 asciipath = UnicodeToAsciiString((LPWSTR)lpPathName);
203 rc = SetCurrentDirectoryA(asciipath);
204 FreeAsciiString(asciipath);
205 return(rc);
206}
207
208
209/*****************************************************************************
210 * Name : CreateDirectoryA
211 * Purpose :
212 * Parameters:
213 * Variables :
214 * Result :
215 * Remark :
216 * Status :
217 *
218 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
219 *****************************************************************************/
220
221ODINFUNCTION2(BOOL, CreateDirectoryA,
222 LPCSTR, lpstrDirectory,
223 PSECURITY_ATTRIBUTES,arg2)
224{
225 int len = strlen(lpstrDirectory);
226
227 // cut off trailing backslashes
228 if ( (lpstrDirectory[len - 1] == '\\') ||
229 (lpstrDirectory[len - 1] == '/') )
230 {
231 LPSTR lpTemp = (LPSTR)_alloca(len);
232 lstrcpynA(lpTemp,
233 lpstrDirectory,
234 len ); // len is including trailing NULL!!
235 lpstrDirectory = lpTemp;
236 }
237
238 dprintf(("CreateDirectoryA %s",
239 lpstrDirectory));
240
241 // PH Note 2000/06/12:
242 // Creation of an existing directory is NO ERROR it seems.
243 DWORD dwAttr = GetFileAttributesA(lpstrDirectory);
244 if (dwAttr != -1)
245 if (dwAttr & FILE_ATTRIBUTE_DIRECTORY)
246 {
247 SetLastError(ERROR_SUCCESS);
248 return TRUE;
249 }
250
251 return(O32_CreateDirectory(lpstrDirectory,
252 arg2));
253}
254
255/*****************************************************************************
256 * Name : CreateDirectoryW
257 * Purpose :
258 * Parameters:
259 * Variables :
260 * Result :
261 * Remark :
262 * Status :
263 *
264 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
265 *****************************************************************************/
266
267ODINFUNCTION2(BOOL,CreateDirectoryW,LPCWSTR, arg1,
268 PSECURITY_ATTRIBUTES,arg2)
269{
270 BOOL rc;
271 char *astring;
272
273 astring = UnicodeToAsciiString((LPWSTR)arg1);
274 rc = CreateDirectoryA(astring, arg2);
275 FreeAsciiString(astring);
276 return(rc);
277}
278
279/*****************************************************************************
280 * Name : BOOL WIN32API CreateDirectoryExA
281 * Purpose : The CreateDirectoryExA function creates a new directory with a
282 * specified path that retains the attributes of a specified
283 * template directory. If the underlying file system supports
284 * security on files and directories, the function applies a
285 * specified security descriptor to the new directory.
286 * The new directory retains the other attributes of the specified
287 * template directory. Note that CreateDirectoryEx has a template
288 * parameter, while CreateDirectory does not.
289 * Parameters: LPCSTR lpTemplateDirectory pointer to path string of template
290 * directory
291 * LPCSTR lpNewDirectory pointer to path string of directory
292 * to create
293 * LPSECURITY_ATTRIBUTES lpSecurityAttributes pointer to security
294 * descriptor
295 *
296 * Variables :
297 * Result : If the function succeeds, the return value is nonzero.
298 * If the function fails, the return value is zero.
299 * To get extended error information, call GetLastError.
300 * Remark :
301 * Status : UNTESTED STUB
302 *
303 * Author : Markus Montkowski [Tha, 1998/05/21 17:46]
304 *****************************************************************************/
305
306BOOL WIN32API CreateDirectoryExA( LPCSTR lpTemplateDirectory,
307 LPCSTR lpNewDirectory,
308 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
309{
310
311 dprintf(("KERNEL32:CreateDirectoryExA(%08x,%08x,%08x) not properly implemented\n",
312 lpTemplateDirectory,lpNewDirectory,lpSecurityAttributes
313 ));
314
315 return CreateDirectoryA(lpNewDirectory, lpSecurityAttributes);
316}
317
318/*****************************************************************************
319 * Name : BOOL WIN32API CreateDirectoryExW
320 * Purpose : The CreateDirectoryExW function creates a new directory with a
321 * specified path that retains the attributes of a specified
322 * template directory. If the underlying file system supports
323 * security on files and directories, the function applies a
324 * specified security descriptor to the new directory.
325 * The new directory retains the other attributes of the specified
326 * template directory. Note that CreateDirectoryEx has a template
327 * parameter, while CreateDirectory does not.
328 * Parameters: LPCWSTR lpTemplateDirectory pointer to path string of template
329 * directory
330 * LPCWSTR lpNewDirectory pointer to path string of directory
331 * to create
332 * LPSECURITY_ATTRIBUTES lpSecurityAttributes pointer to security
333 * descriptor
334 *
335 * Variables :
336 * Result : If the function succeeds, the return value is nonzero.
337 * If the function fails, the return value is zero.
338 * To get extended error information, call GetLastError.
339 * Remark :
340 * Status : UNTESTED STUB
341 *
342 * Author : Markus Montkowski [Tha, 1998/05/21 17:46]
343 *****************************************************************************/
344
345BOOL WIN32API CreateDirectoryExW( LPCWSTR lpTemplateDirectory,
346 LPCWSTR lpNewDirectory,
347 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
348{
349
350 dprintf(("KERNEL32:CreateDirectoryExW(%08x,%08x,%08x) not properly implemented\n",
351 lpTemplateDirectory,lpNewDirectory,lpSecurityAttributes
352 ));
353
354 return CreateDirectoryW(lpNewDirectory, lpSecurityAttributes);
355}
356
357/*****************************************************************************
358 * Name : GetSystemDirectoryA
359 * Purpose :
360 * Parameters:
361 * Variables :
362 * Result :
363 * Remark : Should return length of system dir even if lpBuffer == NULL
364 * Status :
365 *
366 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
367 *****************************************************************************/
368
369ODINFUNCTION2(UINT,GetSystemDirectoryA,LPSTR,lpBuffer,
370 UINT,uSize)
371{
372 int len;
373 char *dir;
374
375 dir = InternalGetSystemDirectoryA();
376 len = lstrlenA(dir);
377 if(lpBuffer)
378 lstrcpynA(lpBuffer, dir, uSize);
379 return len;
380}
381
382
383/*****************************************************************************
384 * Name : GetSystemDirectoryW
385 * Purpose :
386 * Parameters:
387 * Variables :
388 * Result :
389 * Remark : Should return length of system dir even if lpBuffer == NULL
390 * Status :
391 *
392 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
393 *****************************************************************************/
394
395ODINFUNCTION2(UINT,GetSystemDirectoryW,LPWSTR,lpBuffer,
396 UINT, uSize)
397{
398 char *asciibuffer = NULL;
399 UINT rc;
400
401 if(lpBuffer)
402 asciibuffer = (char *)alloca(uSize+1);
403
404 if(lpBuffer && asciibuffer == NULL)
405 {
406 DebugInt3();
407 }
408
409 rc = GetSystemDirectoryA(asciibuffer, uSize);
410 if(rc && asciibuffer)
411 AsciiToUnicode(asciibuffer, lpBuffer);
412
413 return(rc);
414}
415
416
417/*****************************************************************************
418 * Name : GetWindowsDirectoryA
419 * Purpose :
420 * Parameters:
421 * Variables :
422 * Result :
423 * Remark : Should return length of system dir even if lpBuffer == NULL
424 * Status :
425 *
426 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
427 *****************************************************************************/
428
429ODINFUNCTION2(UINT,GetWindowsDirectoryA,LPSTR,lpBuffer,
430 UINT,uSize)
431{
432 char *dir;
433 int len;
434
435 dir = InternalGetWindowsDirectoryA();
436 len = lstrlenA(dir);
437 if(lpBuffer)
438 lstrcpynA(lpBuffer, dir, uSize);
439 return len;
440}
441
442
443/*****************************************************************************
444 * Name : GetWindowsDirectoryW
445 * Purpose :
446 * Parameters:
447 * Variables :
448 * Result :
449 * Remark : Should return length of system dir even if lpBuffer == NULL
450 * Status :
451 *
452 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
453 *****************************************************************************/
454
455ODINFUNCTION2(UINT,GetWindowsDirectoryW,LPWSTR,lpBuffer,
456 UINT, uSize)
457{
458 char *asciibuffer = NULL;
459 UINT rc;
460
461 if(lpBuffer)
462 asciibuffer = (char *)alloca(uSize+1);
463
464 if(lpBuffer && asciibuffer == NULL)
465 {
466 DebugInt3();
467 }
468
469 rc = GetWindowsDirectoryA(asciibuffer, uSize);
470 if(rc && asciibuffer)
471 AsciiToUnicode(asciibuffer, lpBuffer);
472
473 return(rc);
474}
475
476
477/*****************************************************************************
478 * Name : RemoveDirectoryA
479 * Purpose :
480 * Parameters:
481 * Variables :
482 * Result :
483 * Remark :
484 * Status :
485 *
486 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
487 *****************************************************************************/
488
489
490ODINFUNCTION1(BOOL, RemoveDirectoryA,
491 LPCSTR, lpstrDirectory)
492{
493 int len = strlen(lpstrDirectory);
494
495 // cut off trailing backslashes
496 if ( (lpstrDirectory[len - 1] == '\\') ||
497 (lpstrDirectory[len - 1] == '/') )
498 {
499 LPSTR lpTemp = (LPSTR)_alloca(len);
500 lstrcpynA(lpTemp,
501 lpstrDirectory,
502 len ); // len is including trailing NULL!!
503 lpstrDirectory = lpTemp;
504 }
505
506 dprintf(("RemoveDirectory %s",
507 lpstrDirectory));
508
509 return O32_RemoveDirectory(lpstrDirectory);
510}
511
512
513/*****************************************************************************
514 * Name : RemoveDirectoryW
515 * Purpose :
516 * Parameters:
517 * Variables :
518 * Result :
519 * Remark :
520 * Status :
521 *
522 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
523 *****************************************************************************/
524
525ODINFUNCTION1(BOOL,RemoveDirectoryW,LPCWSTR,lpPathName)
526{
527 char *asciipath;
528 BOOL rc;
529
530 asciipath = UnicodeToAsciiString((LPWSTR)lpPathName);
531 rc = RemoveDirectoryA(asciipath);
532 FreeAsciiString(asciipath);
533 return(rc);
534}
535
536/***********************************************************************
537 * DIR_TryModulePath
538 *
539 * Helper function for DIR_SearchPath.
540 */
541static BOOL DIR_TryModulePath( LPCSTR name, char *full_name )
542{
543 char buffer[OFS_MAXPATHNAME];
544 LPSTR p;
545
546 if (!GetModuleFileNameA( 0, buffer, sizeof(buffer) ))
547 buffer[0]='\0';
548
549 if (!(p = strrchr( buffer, '\\' ))) return FALSE;
550 if (sizeof(buffer) - (++p - buffer) <= strlen(name)) return FALSE;
551 strcpy( p, name );
552
553 return OSLibDosSearchPath(OSLIB_SEARCHFILE, NULL, buffer, full_name, MAX_PATHNAME_LEN);
554}
555
556
557/***********************************************************************
558 * DIR_SearchPath
559 *
560 * Implementation of SearchPath32A. 'win32' specifies whether the search
561 * order is Win16 (module path last) or Win32 (module path first).
562 *
563 * FIXME: should return long path names.
564 */
565DWORD DIR_SearchPath( LPCSTR path, LPCSTR name, LPCSTR ext,
566 char *full_name )
567{
568 DWORD len;
569 LPCSTR p;
570 LPSTR tmp = NULL;
571 BOOL ret = TRUE;
572
573 /* First check the supplied parameters */
574
575 p = strrchr( name, '.' );
576 if (p && !strchr( p, '/' ) && !strchr( p, '\\' ))
577 ext = NULL; /* Ignore the specified extension */
578 if ((*name && (name[1] == ':')) ||
579 strchr( name, '/' ) || strchr( name, '\\' ))
580 path = NULL; /* Ignore path if name already contains a path */
581 if (path && !*path) path = NULL; /* Ignore empty path */
582
583 len = strlen(name);
584 if (ext) len += strlen(ext);
585 if (path) len += strlen(path) + 1;
586
587 /* Allocate a buffer for the file name and extension */
588
589 if (path || ext)
590 {
591 if (!(tmp = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len + 1 )))
592 {
593 SetLastError( ERROR_OUTOFMEMORY );
594 return 0;
595 }
596 if (path)
597 {
598 strcpy( tmp, path );
599 strcat( tmp, "\\" );
600 strcat( tmp, name );
601 }
602 else strcpy( tmp, name );
603 if (ext) strcat( tmp, ext );
604 name = tmp;
605 }
606
607 /* If we have an explicit path, everything's easy */
608
609 if (path || (*name && (name[1] == ':')) ||
610 strchr( name, '/' ) || strchr( name, '\\' ))
611 {
612 ret = OSLibDosSearchPath(OSLIB_SEARCHFILE, NULL, (LPSTR)name, full_name, MAX_PATHNAME_LEN);
613 goto done;
614 }
615
616 /* Try the path of the current executable (for Win32 search order) */
617 if (DIR_TryModulePath( name, full_name )) goto done;
618
619 /* Try the current directory */
620 if (OSLibDosSearchPath(OSLIB_SEARCHCURDIR, NULL, (LPSTR)name, full_name, MAX_PATHNAME_LEN))
621 goto done;
622
623 /* Try the Windows system directory */
624 if (OSLibDosSearchPath(OSLIB_SEARCHDIR, (LPSTR)&DIR_System, (LPSTR)name, full_name, MAX_PATHNAME_LEN))
625 goto done;
626
627 /* Try the Windows directory */
628 if (OSLibDosSearchPath(OSLIB_SEARCHDIR, (LPSTR)&DIR_Windows, (LPSTR)name, full_name, MAX_PATHNAME_LEN))
629 goto done;
630
631 /* Try all directories in path */
632 ret = OSLibDosSearchPath(OSLIB_SEARCHENV, "PATH", (LPSTR)name, full_name, MAX_PATHNAME_LEN);
633
634done:
635 if (tmp) HeapFree( GetProcessHeap(), 0, tmp );
636 return ret;
637}
638
639
640/***********************************************************************
641 * SearchPath32A [KERNEL32.447]
642 *
643 * Searches for a specified file in the search path.
644 *
645 * PARAMS
646 * path [I] Path to search
647 * name [I] Filename to search for.
648 * ext [I] File extension to append to file name. The first
649 * character must be a period. This parameter is
650 * specified only if the filename given does not
651 * contain an extension.
652 * buflen [I] size of buffer, in characters
653 * buffer [O] buffer for found filename
654 * lastpart [O] address of pointer to last used character in
655 * buffer (the final '\')
656 *
657 * RETURNS
658 * Success: length of string copied into buffer, not including
659 * terminating null character. If the filename found is
660 * longer than the length of the buffer, the length of the
661 * filename is returned.
662 * Failure: Zero
663 *
664 * NOTES
665 * Should call SetLastError(but currently doesn't).
666 */
667DWORD WINAPI SearchPathA(LPCSTR path, LPCSTR name, LPCSTR ext, DWORD buflen,
668 LPSTR buffer, LPSTR *lastpart )
669{
670 char full_name[MAX_PATHNAME_LEN];
671
672 if (!DIR_SearchPath( path, name, ext, (LPSTR)full_name )) return 0;
673 lstrcpynA( buffer, (LPSTR)full_name, buflen);
674 SetLastError(0);
675 return strlen(buffer);
676}
677
678
679/***********************************************************************
680 * SearchPath32W (KERNEL32.448)
681 */
682DWORD WINAPI SearchPathW(LPCWSTR path, LPCWSTR name, LPCWSTR ext,
683 DWORD buflen, LPWSTR buffer, LPWSTR *lastpart )
684{
685 char full_name[MAX_PATHNAME_LEN];
686
687 LPSTR pathA = HEAP_strdupWtoA( GetProcessHeap(), 0, path );
688 LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
689 LPSTR extA = HEAP_strdupWtoA( GetProcessHeap(), 0, ext );
690 DWORD ret = DIR_SearchPath( pathA, nameA, extA, (LPSTR)full_name );
691 HeapFree( GetProcessHeap(), 0, extA );
692 HeapFree( GetProcessHeap(), 0, nameA );
693 HeapFree( GetProcessHeap(), 0, pathA );
694 if (!ret) return 0;
695
696 lstrcpynAtoW( buffer, full_name, buflen);
697 SetLastError(0);
698 return strlen(full_name);
699}
Note: See TracBrowser for help on using the repository browser.