|
|
1.1 root 1: /*************************************************************************\
2: * PROGRAM: setinfo.c
3: *
4: * PURPOSE:
5: *
6: * To demonstrate queries and setting file information much as the
7: * OS/2 API's DosQFileInfo() and DosSetFileInfo().
8: *
9: * GLOBAL VARIABLES:
10: *
11: * HANDLE hInst; - Instance handle.
12: *
13: * HWND hWnd; - Client window handle.
14: *
15: * HWND hWndDlg;- Window handle to upper dialog box.
16: *
17: * HWND hWndFileDlg;
18: * - Window handle to lower dialog box.
19: *
20: * DWORD StepTime;
21: * - Time in ms., used to control the speed of reporting
22: * return codes in the upper dialog box.
23: *
24: * FUNCTIONS:
25: *
26: * WinMain() - Initializes the window, and process the message loop.
27: * MainWndProc() - To handle the messages to the main window.
28: * StatusDlgProc()- To handle messages to the Status Dialog (upper) box.
29: * FileDlgProc() - To handle messages to the File Dialog (lower) box.
30: * RepStat() - To calculate return codes and to send results as
31: * messages to the StatusDlgProc()
32: *
33: * COMMENTS:
34: *
35: * Overview:
36: * This sample captures and sets a files date/time, size, and
37: * attributes information (note it does not *set* file size
38: * information). It also reports API return code status
39: * information.
40: *
41: * To Use:
42: * Enter a file name into the appropriate edit field, and click on
43: * the Get Info. button. File information will be retrieved and
44: * placed in the various edit fields and check buttons. To set
45: * file information, modify the values in the Time and Date edit
46: * fields, and click the Set Info. button. To set file attributes,
47: * set the approprate check boxes, and click on the Set Attr. button.
48: * Note this application does not check for rediculous Date and Time
49: * information, and does not understand i.e. values before 1980 or after
50: * 2099. The API are left to deal with such values as best they
51: * can.
52: *
53: * As the buttons are clicked the code sends return code status
54: * information to be reported in the upper dialog box. The user
55: * can leave this reporting to be done at default time ( 0ms. Sleep
56: * between each API), or can enter a time in the appropriate box
57: * and clicking the Set Time button. This will put a Sleep between
58: * the API call so that the user can more easily read the return
59: * codes.
60: *
61: * Time Conversion:
62: * Note that GetFileTime() and SetFileTime() use 64 bit FILETIME
63: * structures. These structure consist of two DWORD fields: which
64: * represent file time in hundreds of nano-seconds. This file time
65: * can be converted into DosDate time (or back again) with the
66: * FileTimeToDosDateTime() and DosDateTimeToFileTime() calls. These
67: * calls use WORD values representing DosDate and DosTime. The
68: * online Windows .hlp files will tell you how these WORDs break
69: * down into days, months, hours, seconds, etc. This sample uses
70: * a combination of masking and shifting to extract the values
71: * from the file (see the FileDlgProc() and the symbolic constants
72: * mask defined in the header file). Other points of interest are
73: * that seconds are stored in 2 second increments (1-29), and that
74: * years are represented from 1980 (meaning i.e. 1992 will be
75: * be represented by 12).
76: *
77: *
78: \*************************************************************************/
79:
80: #include <windows.h>
81: #include <stdlib.h>
82: #include "setinfo.h"
83:
84:
85: HANDLE hInst;
86: HWND hWnd, hWndDlg, hWndFileDlg;
87: DWORD StepTime;
88:
89:
90:
91: /*************************************************************************\
92: *
93: * FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
94: *
95: * PURPOSE: Calls initialization function, processes message loop.
96: *
97: * COMMENTS: A fairly standard WinMain, with the exception that it
98: * creates two modeless dialog boxes which fit over the window.
99: * Note the use of IsDialogMessage in the message loop. This
100: * call not only returns a boolean value, but also processes
101: * the message if it is a dialog box message; otherwise the
102: * message falls through to the body of the loop to be translated
103: * and dispatched.
104: *
105: \*************************************************************************/
106:
107: int APIENTRY WinMain (HANDLE hInstance,
108: HANDLE hPrevInstance,
109: LPSTR lpCmdLine,
110: int nCmdShow)
111:
112:
113: {
114:
115: MSG msg;
116: WNDCLASS wc;
117: RECT rect;
118:
119: UNREFERENCED_PARAMETER( lpCmdLine );
120: UNREFERENCED_PARAMETER( hPrevInstance );
121:
122: hInst = hInstance;
123:
124: wc.style = NULL; // Replaces CS_SIZEREDRAW.
125: wc.lpfnWndProc = (WNDPROC)MainWndProc; // The client window procedure.
126: wc.cbClsExtra = 0; // No room reserved for extra data.
127: wc.cbWndExtra = 0;
128: wc.hInstance = hInstance;
129: wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
130: wc.hCursor = LoadCursor (NULL, IDC_ARROW);
131: wc.hbrBackground = GetStockObject (WHITE_BRUSH);
132: wc.lpszMenuName = "";
133: wc.lpszClassName = "SetInfoWClass";
134:
135: RegisterClass(&wc);
136:
137: hWnd = CreateWindow ("SetInfoWClass",
138: "Set File Info. Sample",
139: WS_OVERLAPPEDWINDOW,
140: CW_USEDEFAULT,
141: CW_USEDEFAULT,
142: CW_USEDEFAULT,
143: CW_USEDEFAULT,
144: NULL,
145: NULL,
146: hInstance,
147: NULL);
148:
149: hWndDlg = CreateDialog (hInst, "StatusDlg", hWnd, StatusDlgProc);
150: hWndFileDlg = CreateDialog (hInst, "FileDlg", hWnd, FileDlgProc);
151:
152: GetClientRect (hWnd, &rect);
153: SendMessage (hWnd, WM_SIZE, 0, (rect.right - rect.left));
154: ShowWindow (hWndDlg, SW_SHOW);
155: ShowWindow (hWndFileDlg, SW_SHOW);
156: ShowWindow (hWnd, nCmdShow);
157:
158: while (GetMessage (&msg, NULL, NULL, NULL))
159: if (!IsDialogMessage (hWndDlg, &msg)
160: && !IsDialogMessage (hWndFileDlg, &msg))
161: {
162: DispatchMessage (&msg); // Dispatch message to window.
163: }
164:
165: return (msg.wParam); // Returns value from PostQuitMessage.
166:
167: }
168:
169: /*************************************************************************\
170: *
171: * FUNCTION: MainWndProc (HWND, UINT, UINT, LONG)
172: *
173: * PURPOSE: To process messages. To launch client and server threads
174: * as appropriate.
175: *
176: * VARIABLES USED:
177: *
178: * - hWndDlg:
179: * Global window handle for the upper dialog box.
180: *
181: * - hWndFileDlg:
182: * Global window handle for the lower dialog box.
183: *
184: * MESSAGES:
185: *
186: * WM_DESTROY - Standard, destroys the window.
187: * WM_SIZE - Sends messages to the two dialog boxes so that they
188: * maintain their relative size to the client window.
189: *
190: * CALLED BY:
191: *
192: * WinMain();
193: *
194: \*************************************************************************/
195:
196: LONG APIENTRY MainWndProc (HWND hwnd,
197: UINT message,
198: UINT wParam,
199: LONG lParam)
200: {
201: switch (message)
202: {
203:
204: case WM_SIZE :
205: SetWindowPos (hWndDlg, NULL, 0,0, LOWORD(lParam), DIALOGHEIGHT, NULL);
206: SetWindowPos (hWndFileDlg, NULL, 0,DIALOGHEIGHT, LOWORD(lParam), HIWORD(lParam), NULL);
207: return (0);
208:
209: case WM_DESTROY :
210: PostQuitMessage (0);
211: return (0);
212:
213: }
214: return DefWindowProc (hwnd, message, wParam, lParam);
215: }
216:
217: /*************************************************************************\
218: *
219: * FUNCTION: StatusDlgProc (HWND, UINT, UINT, LONG)
220: *
221: * PURPOSE: To process messages for the upper dialog box.
222: *
223: * VARIABLES USED:
224: *
225: * - StepTime:
226: * A global DWORD holding the value of the sleep time between
227: * API calls.
228: *
229: * - bTranslated:
230: * A local BOOL needed for GetDlgItemInt().
231: *
232: * MESSAGES:
233: *
234: * WM_INITDIALOG: - Sets a "0" in the time edit field IDE_TIME. This
235: * is to indicate to the user that the default time
236: * set to sleep between reporting the results of
237: * API calls is set to 0.
238: *
239: * WM_REPSTAT: - A user defined message. This message uses wParam
240: * as a pointer to a string holding an API i.e.
241: * "CreateFile()". It uses lParam to hold a string
242: * reporting the value of returned by the API i.e.
243: * "ERROR_ACCESS_DENIED", or a number if the return
244: * value isn't identified in RepStat(). The code
245: * then places these strings in the IDE_API and
246: * IDE_REPSTAT edit fields.
247: *
248: * WM_COMMAND
249: *
250: * IDM_STEP: - Captures the time value in the IDE_TIME edit
251: * field, and then sets that value into the
252: * global DWORD StepTime. This value sets
253: * a sleep time inbetween reporting the results of
254: * each API (making it easier for the user to read).
255: *
256: * COMMENTS:
257: *
258: * This procedure controls the upper dialog box of the application.
259: * The purpose of this box is to report on the API being used by
260: * the lower box, and it's return code. It also allows you to control
261: * the speed that the application steps through these calls. This is
262: * basically a error checking/debugging feature, but it also lends an
263: * intuitive look at the API being used.
264: *
265: \*************************************************************************/
266:
267: LONG APIENTRY StatusDlgProc (HWND hDlg, UINT message, UINT wParam, LONG lParam)
268: {
269: BOOL bTranslated;
270:
271: UNREFERENCED_PARAMETER (wParam);
272: UNREFERENCED_PARAMETER (lParam);
273:
274: switch (message)
275: {
276: case WM_INITDIALOG:
277: StepTime = 0;
278: SetDlgItemInt (hDlg, IDE_TIME, StepTime, FALSE);
279: return (0);
280:
281: case WM_REPSTAT:
282: SetDlgItemText (hDlg, IDE_API,(LPTSTR) wParam);
283: SetDlgItemText (hDlg, IDE_RETSTAT, (LPTSTR)lParam);
284: return (0);
285:
286: case WM_COMMAND:
287: switch (LOWORD(wParam))
288: {
289: case IDB_STEP:
290: StepTime = GetDlgItemInt (hDlg, IDE_TIME, &bTranslated, FALSE);
291: }
292: }
293: return (0);
294: }
295:
296: /*************************************************************************\
297: *
298: * FUNCTION: FileDlgProc (HWND, UINT, UINT, LONG)
299: *
300: * PURPOSE: To process the messages to the lower dialog box.
301: *
302: * VARIABLES USED:
303: *
304: * - fileName:
305: * A local CHAR array used to capture the text from the
306: * IDE_FILENAME edit field.
307: *
308: * - hFile: Local file handle.
309: *
310: * - retCode:
311: * Local DWORD used to trap API return codes.
312: *
313: * - ftCreation,
314: * - ftAccessed,
315: * - ftWrittenTo:
316: * Local FILETIME structures.
317: *
318: * - wDosDate,
319: * - wDosTime:
320: * Local WORDs, used to hold the values converted from the
321: * FILETIME structures converted by FileTimeToDosDateTime()
322: * and DosDateTimeToFileTime().
323: *
324: * - DD[],
325: * - MM[],
326: * - YY[],
327: * - Mn[],
328: * - SS[],
329: * - HH[]: Local CHAR arrays used to trap the values in various
330: * edit fields representing date and time values.
331: *
332: * - dwFileSize:
333: * Local DWORD holding file size.
334: *
335: * - lpsFileSize[]:
336: * Local CHAR array used to trap the string from the IDE_SIZE
337: * edit field.
338: *
339: * - dwFileAttr:
340: * Local DWORD holding the file attributes.
341: *
342: * - hDlg: Input parameter, handle to the dialog box.
343: *
344: * MESSAGES:
345: *
346: * WM_COMMAND
347: *
348: * IDB_ATTR:
349: * It initializes the variable to hold the file attributes,
350: * dwFileAttr, and then traps the checked states of the
351: * dialog boxes checked buttons. If a box is found to be
352: * checked, then the appropriate file attribute flag is
353: * OR'd into dwFileAttr. When all of the attribute values
354: * have been collected, these attributes are set to the file
355: * listed in IDE_FILENAME.
356: *
357: * IDB_SET:
358: * This collects the values from the various time and date
359: * edit fields, converts them into system time, and sets
360: * them to the file listed in IDE_FILENAME. Basically the
361: * technique is to 1) get the values from the edit fields;
362: * 2) shift them to their correct location in the WORD; and
363: * 3) OR them together into a single WORD.
364: *
365: * IDB_OPENFILE:
366: * This gets the date, time, size, and attribute information
367: * from the file listed in IDE_FILENAME. It converts the
368: * values appropriately and puts them into the various
369: * edit fields and check buttons. Again, to do time and date
370: * conversions, you must AND the values returned from
371: * GetFileTime() with certain masks to let the appropriate bits
372: * fall through from the WORD (see the mask and shift values
373: * in the setinfo.h file), and shift them to the low order
374: * bit to get the new values. This is done in the wsprintf()
375: * call's parameter list.
376: *
377: * CALLS TO:
378: *
379: * RepStat();
380: *
381: * COMMENTS:
382: * The basic function of this box is to capture and set file information,
383: * and to send messages to the upper dialog box via RepStat() to report
384: * return code information. Special characteristics of this function
385: * is how to get and set file information and attributes, and how to
386: * convert Time and Date information.
387: *
388: \*************************************************************************/
389:
390: LONG APIENTRY FileDlgProc (HWND hDlg, UINT message, UINT wParam, LONG lParam)
391: {
392: CHAR fileName[100];
393: HANDLE hFile;
394: DWORD retCode = 0;
395: FILETIME ftCreation, ftAccessed, ftWrittenTo;
396: WORD wDosDate, wDosTime;
397: CHAR DD[3], MM[3], YY[3], HH[3], Mn[3], SS[3];
398: DWORD dwFileSize;
399: CHAR lpsFileSize[10];
400: DWORD dwFileAttr;
401:
402: UNREFERENCED_PARAMETER (wParam);
403: UNREFERENCED_PARAMETER (lParam);
404:
405: switch (message)
406: {
407:
408: case WM_COMMAND :
409: switch (LOWORD(wParam))
410: {
411: case IDB_ATTR:
412:
413: dwFileAttr = 0;
414:
415: if (IsDlgButtonChecked (hDlg, IDC_HIDE))
416: dwFileAttr |= FILE_ATTRIBUTE_HIDDEN;
417:
418: if (IsDlgButtonChecked (hDlg, IDC_NORMAL))
419: dwFileAttr |= FILE_ATTRIBUTE_NORMAL;
420:
421: if (IsDlgButtonChecked (hDlg, IDC_ARC))
422: dwFileAttr |= FILE_ATTRIBUTE_ARCHIVE;
423:
424: if (IsDlgButtonChecked (hDlg, IDC_SYSTEM))
425: dwFileAttr |= FILE_ATTRIBUTE_SYSTEM;
426:
427: if (IsDlgButtonChecked (hDlg, IDC_READ))
428: dwFileAttr |= FILE_ATTRIBUTE_READONLY;
429:
430: GetDlgItemText (hDlg, IDE_FILENAME, fileName, 100);
431:
432: retCode = SetFileAttributes (fileName, dwFileAttr);
433: RepStat ("SetFileAttributes()", retCode);
434:
435: return (0);
436:
437: case IDB_SET:
438:
439: GetDlgItemText (hDlg, IDE_YEAR, YY, 3);
440: GetDlgItemText (hDlg, IDE_DAY, DD, 3);
441: GetDlgItemText (hDlg, IDE_MONTH, MM, 3);
442: wDosDate = (WORD)((atoi(YY) - 80)<<YRSHIFT |
443: atoi(MM)<<MONSHIFT |
444: atoi(DD)<<DAYSHIFT);
445:
446: GetDlgItemText (hDlg, IDE_HOURS, HH, 3);
447: GetDlgItemText (hDlg, IDE_SECONDS, SS, 3);
448: GetDlgItemText (hDlg, IDE_MINUTES, Mn, 3);
449: wDosTime = (WORD)((atoi(SS) / 2)<< SECSHIFT |
450: atoi(Mn)<<MINSHIFT |
451: atoi(HH)<<HRSHIFT);
452:
453: retCode = DosDateTimeToFileTime (wDosDate, wDosTime, &ftWrittenTo);
454: RepStat("DosDateTimeToFileTime()", retCode);
455:
456: GetDlgItemText (hDlg, IDE_FILENAME, fileName, 100);
457: hFile = CreateFile (fileName,
458: GENERIC_READ | GENERIC_WRITE,
459: FILE_SHARE_READ | FILE_SHARE_WRITE,
460: NULL,
461: OPEN_EXISTING,
462: FILE_ATTRIBUTE_NORMAL,
463: NULL);
464: if (RepStat("CreateFile()", (DWORD)hFile))
465: return (0);
466:
467:
468: retCode = SetFileTime (hFile, NULL, NULL, &ftWrittenTo);
469: RepStat("SetFileTime()", retCode);
470:
471: CloseHandle (hFile);
472: return (0);
473:
474:
475: case IDB_OPENFILE :
476: GetDlgItemText (hDlg, IDE_FILENAME, fileName, 100);
477: hFile = CreateFile (fileName,
478: GENERIC_READ,
479: FILE_SHARE_READ | FILE_SHARE_WRITE,
480: NULL,
481: OPEN_EXISTING,
482: FILE_ATTRIBUTE_NORMAL,
483: NULL);
484: if (RepStat("CreateFile()", (DWORD)hFile))
485: return (0);
486:
487: (BOOL)retCode = GetFileTime (hFile,
488: &ftCreation,
489: &ftAccessed,
490: &ftWrittenTo);
491: RepStat( "GetFileTime()", retCode);
492:
493: (BOOL)retCode = FileTimeToDosDateTime( &ftWrittenTo,
494: &wDosDate,
495: &wDosTime);
496: RepStat("FileTimeToDosDateTime()", retCode);
497:
498: dwFileSize = GetFileSize (hFile, NULL);
499: RepStat("GetFileSize()", dwFileSize);
500:
501:
502: wsprintf(YY, "%02d", ((wDosDate & YRMASK) >> YRSHIFT ) + 80);
503: SetDlgItemText (hDlg, IDE_YEAR, YY);
504:
505: wsprintf(MM, "%02d", ((wDosDate & MONMASK) >> MONSHIFT));
506: SetDlgItemText (hDlg, IDE_MONTH, MM);
507:
508: wsprintf(DD, "%02d", ((wDosDate & DAYMASK) >> DAYSHIFT) );
509: SetDlgItemText (hDlg, IDE_DAY, DD);
510:
511: wsprintf(SS, "%02d", ((wDosTime & SECMASK) >> SECSHIFT ) * 2);
512: SetDlgItemText (hDlg, IDE_SECONDS, SS);
513:
514: wsprintf(Mn, "%02d", ((wDosTime & MINMASK) >> MINSHIFT));
515: SetDlgItemText (hDlg, IDE_MINUTES, Mn);
516:
517: wsprintf(HH, "%02d", (DWORD)(wDosTime & HRMASK) >> HRSHIFT );
518: SetDlgItemText (hDlg, IDE_HOURS, HH);
519:
520: wsprintf(lpsFileSize, "%d", dwFileSize);
521: SetDlgItemText (hDlg, IDE_SIZE, lpsFileSize);
522:
523: dwFileAttr = GetFileAttributes (fileName);
524: RepStat("GetFileAttributes()", dwFileAttr);
525:
526: if (dwFileAttr & FILE_ATTRIBUTE_NORMAL)
527: CheckDlgButton (hDlg, IDC_NORMAL, TRUE);
528: else
529: CheckDlgButton (hDlg, IDC_NORMAL, FALSE);
530:
531: if (dwFileAttr & FILE_ATTRIBUTE_READONLY)
532: CheckDlgButton (hDlg, IDC_READ, TRUE);
533: else
534: CheckDlgButton (hDlg, IDC_READ, FALSE);
535:
536: if (dwFileAttr & FILE_ATTRIBUTE_HIDDEN)
537: CheckDlgButton (hDlg, IDC_HIDE, TRUE);
538: else
539: CheckDlgButton (hDlg, IDC_HIDE, FALSE);
540:
541: if (dwFileAttr & FILE_ATTRIBUTE_SYSTEM)
542: CheckDlgButton (hDlg, IDC_SYSTEM, TRUE);
543: else
544: CheckDlgButton (hDlg, IDC_SYSTEM, FALSE);
545:
546: if (dwFileAttr & FILE_ATTRIBUTE_ARCHIVE)
547: CheckDlgButton (hDlg, IDC_ARC, TRUE);
548: else
549: CheckDlgButton (hDlg, IDC_ARC, FALSE);
550:
551: CloseHandle (hFile);
552:
553: return (0);
554: }
555: }
556: return (0);
557: }
558:
559: /*************************************************************************\
560: *
561: * FUNCTION: RepStat (CHAR *, DWORD)
562: *
563: * PURPOSE: To report return code information to the upper dialog box.
564: *
565: * VARIABLES USED:
566: *
567: * - TempBufW[],
568: * - TempBufL[]:
569: * Local CHAR arrays used to set the lParam and wParam of
570: * the WM_REPSTAT message.
571: *
572: * - StepTime:
573: * Global DWORD representing the amount of sleep time chosen
574: * by the user.
575: *
576: * CALLED BY:
577: *
578: * FileDlgProc();
579: *
580: * COMMENTS:
581: *
582: * This function receives a string representing an API, and a DWORD
583: * representing it's return code value. It checks the return code to
584: * see if it indicates an error. If so, GetLastError is called to find
585: * the extended error information; if not, then retCode is set to 0.
586: * The case statement is used to exchange the retCode value for
587: * it's more intuitive string counterpart. If no counterpart
588: * is listed, the function just sends the number value in string
589: * form. Note that retCode 0 is just sent as a string number.
590: * Once the function drops from the switch statment, it sends the
591: * user define WM_REPSTAT message to the upper dialog box with the
592: * API and retCode information. It will then enter a Sleep of a
593: * duration determined by the global StepTime value (set by the
594: * user through and edit field. The function returns a boolean
595: * value so that the calling procedure can determine if it wants
596: * to continue processing or break.
597: *
598: \*************************************************************************/
599:
600:
601: BOOL RepStat (CHAR *API, DWORD retCode)
602: {
603: CHAR TempBufW[40];
604: CHAR TempBufL[40];
605:
606: wsprintf(TempBufW, API);
607:
608: if ((int)retCode <= 0 )
609: retCode = GetLastError();
610: else
611: retCode = 0;
612:
613: if (retCode)
614: MessageBeep(0);
615:
616: switch (retCode)
617: {
618: case ERROR_INVALID_FUNCTION: // 1L
619: wsprintf(TempBufL, "ERROR_INVALID_FUNCTION");
620: break;
621:
622: case ERROR_FILE_NOT_FOUND: // 2L
623: wsprintf(TempBufL, "ERROR_FILE_NOT_FOUND");
624: break;
625:
626: case ERROR_ACCESS_DENIED: // 5L
627: wsprintf(TempBufL, "ERROR_ACCESS_DENIED");
628: break;
629:
630: case ERROR_INVALID_HANDLE: // 6L
631: wsprintf(TempBufL, "ERROR_INVALID_HANDLE");
632: break;
633:
634: case ERROR_INVALID_PARAMETER: // 87L
635: wsprintf(TempBufL, "ERROR_INVALID_HANDLE");
636: break;
637:
638: case ERROR_INVALID_NAME: // 123L
639: wsprintf(TempBufL, "ERROR_INVALID_NAME");
640: break;
641:
642: default:
643: wsprintf(TempBufL, "%d", retCode);
644: }
645:
646: SendMessage (hWndDlg, WM_REPSTAT, (DWORD)TempBufW, (LONG)TempBufL);
647: Sleep( StepTime );
648:
649: return (retCode != 0);
650: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.